In Displaying Python Script Outputs on Conky Panels, I suggested running a Python script on a Conky panel to display Bitcoin exchange rates in USD and BRL. However, due to higher-than-expected memory consumption for such a basic task, I rewrote the script in Go. Now, a compiled binary handles the task. This approach is ideal for Go beginners, offering a chance to learn API handling and text formatting for monetary values. Here's a breakdown:
The complete code is at the end of this article.
1 - Packages and Imports
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"strconv"
"github.com/dustin/go-humanize"
)
-
package main
: Marks this as the entry point of the program. -
Imported Libraries:
-
encoding/json
: For parsing JSON responses from APIs. -
fmt
: For text formatting and printing. -
io
: For reading response bodies. -
net/http
: For making HTTP requests. -
strconv
: For converting strings to numbers. -
humanize
: For adding thousand separators to numbers. Install viago get github.com/dustin/go-humanize
.
-
2 - Global Constants
const (
apiURL = "https://economia.awesomeapi.com.br/json/last/BTC-USD,BTC-BRL"
)
-
apiURL
: The API endpoint to fetch Bitcoin exchange rates.
3 - Structures for JSON Parsing
type CurrencyData struct {
High string `json:"high"`
Low string `json:"low"`
}
type APIResponse struct {
BTCUSD CurrencyData `json:"BTCUSD"`
BTCBRL CurrencyData `json:"BTCBRL"`
}
-
CurrencyData
: Holds high and low values for a currency. -
APIResponse
: Represents the full API response withBTCUSD
andBTCBRL
keys.
JSON tags (json:"high"
) map struct fields to JSON keys.
4 - Function to Format Monetary Values
func formatCurrency(value string, prefix string) string {
floatValue, err := strconv.ParseFloat(value, 64)
if err != nil {
return "N/A"
}
formattedValue := fmt.Sprintf("%s%s", prefix, humanize.FormatFloat("#,###.##", floatValue))
return formattedValue
}
- Converts
value
(string) to a float usingstrconv.ParseFloat
. - Formats the number with thousand separators and two decimal places, adding the
prefix
(e.g.,$
orR$
).
5 - Main Function
5.1 API Request
resp, err := http.Get(apiURL)
if err != nil {
writeError(err)
return
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
writeError(err)
return
}
-
http.Get(apiURL)
: Sends a GET request to the API. -
defer resp.Body.Close()
: Ensures the response body is closed after processing. -
io.ReadAll
: Reads the response body.
5.2 JSON Parsing
var data APIResponse
if err := json.Unmarshal(body, &data); err != nil {
writeError(err)
return
}
-
json.Unmarshal
: Parses the JSON response into theAPIResponse
struct.
5.3 Data Formatting
usdAlta := formatCurrency(data.BTCUSD.High, "$$")
usdBaixa := formatCurrency(data.BTCUSD.Low, "$$")
brlAlta := formatCurrency(data.BTCBRL.High, "R$$")
brlBaixa := formatCurrency(data.BTCBRL.Low, "R$$")
Formats the API-provided values for display.
5.4 Result Construction
formattedData := fmt.Sprintf(
"\n\n${color white}BTC - USD\n${color}${color green} High: ${color}${color white}%s\n${color red} Low: ${color}${color white}%s\n\n"+
"${color white}BTC - BRL\n${color}${color green} High: ${color}${color white}%s\n${color red} Low: ${color}${color white}%s\n",
usdAlta, usdBaixa, brlAlta, brlBaixa,
)
fmt.Println(formattedData)
Creates the final output string with the formatted values.
6 - Error Logging Function
func writeError(err error) {
errMsg := fmt.Sprintf("Error: %v", err)
fmt.Println(errMsg)
}
Logs errors to the terminal.
🪙 btc_data.go
Run: go build btc_data.go && ./btc_data.go
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"strconv"
"github.com/dustin/go-humanize"
)
const (
apiURL = "https://economia.awesomeapi.com.br/json/last/BTC-USD,BTC-BRL"
)
type CurrencyData struct {
High string `json:"high"`
Low string `json:"low"`
}
type APIResponse struct {
BTCUSD CurrencyData `json:"BTCUSD"`
BTCBRL CurrencyData `json:"BTCBRL"`
}
func formatCurrency(value string, prefix string) string {
floatValue, err := strconv.ParseFloat(value, 64)
if err != nil {
return "N/A"
}
formattedValue := fmt.Sprintf("%s%s", prefix, humanize.FormatFloat("#,###.##", floatValue))
return formattedValue
}
func main() {
resp, err := http.Get(apiURL)
if err != nil {
writeError(err)
return
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
writeError(err)
return
}
var data APIResponse
if err := json.Unmarshal(body, &data); err != nil {
writeError(err)
return
}
usdAlta := formatCurrency(data.BTCUSD.High, "$$")
usdBaixa := formatCurrency(data.BTCUSD.Low, "$$")
brlAlta := formatCurrency(data.BTCBRL.High, "R$$")
brlBaixa := formatCurrency(data.BTCBRL.Low, "R$$")
formattedData := fmt.Sprintf(
"\n\n${color white}BTC - USD\n${color}${color green} High: ${color}${color white}%s\n${color red} Low: ${color}${color white}%s\n\n"+
"${color white}BTC - BRL\n${color}${color green} High: ${color}${color white}%s\n${color red} Low: ${color}${color white}%s\n",
usdAlta, usdBaixa, brlAlta, brlBaixa,
)
fmt.Println(formattedData)
}
func writeError(err error) {
errMsg := fmt.Sprintf("Error: %v", err)
fmt.Println(errMsg)
}
If this article helped you or you enjoyed it, consider contributing:
Top comments (0)