DEV Community

Everton Tenorio
Everton Tenorio

Posted on

Bitcoin Rates Script in Go

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"
)
Enter fullscreen mode Exit fullscreen mode
  • 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 via go get github.com/dustin/go-humanize.

2 - Global Constants

const (
    apiURL = "https://economia.awesomeapi.com.br/json/last/BTC-USD,BTC-BRL"
)
Enter fullscreen mode Exit fullscreen mode
  • 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"`
}
Enter fullscreen mode Exit fullscreen mode
  • CurrencyData: Holds high and low values for a currency.
  • APIResponse: Represents the full API response with BTCUSD and BTCBRL 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
}
Enter fullscreen mode Exit fullscreen mode
  • Converts value (string) to a float using strconv.ParseFloat.
  • Formats the number with thousand separators and two decimal places, adding the prefix (e.g., $ or R$).

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
}
Enter fullscreen mode Exit fullscreen mode
  • 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
}
Enter fullscreen mode Exit fullscreen mode
  • json.Unmarshal: Parses the JSON response into the APIResponse 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$$")
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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)
}
Enter fullscreen mode Exit fullscreen mode

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)
}
Enter fullscreen mode Exit fullscreen mode

If this article helped you or you enjoyed it, consider contributing: donate

Top comments (0)