Fetch live and historical exchange rates in Go. Use net/http and encoding/json from the standard library to build a currency converter.
Fetch your first exchange rate using Go's standard library. No external dependencies required.
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
)
type Rate struct {
Rate float64 `json:"rate"`
Source string `json:"source"`
Target string `json:"target"`
Time string `json:"time"`
}
func main() {
req, _ := http.NewRequest("GET",
"https://exchange-rateapi.com/api/v1/rates?source=USD&target=EUR", nil)
req.Header.Set("Authorization", "Bearer era_live_YOUR_API_KEY")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
var rates []Rate
json.NewDecoder(resp.Body).Decode(&rates)
fmt.Printf("1 USD = %.4f EUR\n", rates[0].Rate)
// Output: 1 USD = 0.9215 EUR
}
era_live_. The free plan includes 300 requests per month.
Here is a production-ready example with proper error handling, timeouts, and a reusable client struct.
package main
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
"time"
)
type Rate struct {
Rate float64 `json:"rate"`
Source string `json:"source"`
Target string `json:"target"`
Time string `json:"time"`
}
type ExchangeRateClient struct {
apiKey string
client *http.Client
}
func NewClient(apiKey string) *ExchangeRateClient {
return &ExchangeRateClient{
apiKey: apiKey,
client: &http.Client{Timeout: 10 * time.Second},
}
}
func (c *ExchangeRateClient) GetRates(ctx context.Context, source, target string) ([]Rate, error) {
u, _ := url.Parse("https://exchange-rateapi.com/api/v1/rates")
q := u.Query()
q.Set("source", source)
q.Set("target", target)
u.RawQuery = q.Encode()
req, err := http.NewRequestWithContext(ctx, "GET", u.String(), nil)
if err != nil {
return nil, fmt.Errorf("creating request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+c.apiKey)
resp, err := c.client.Do(req)
if err != nil {
return nil, fmt.Errorf("executing request: %w", err)
}
defer resp.Body.Close()
switch resp.StatusCode {
case http.StatusUnauthorized:
return nil, fmt.Errorf("invalid API key")
case http.StatusTooManyRequests:
return nil, fmt.Errorf("rate limit exceeded")
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected status: %d", resp.StatusCode)
}
var rates []Rate
if err := json.NewDecoder(resp.Body).Decode(&rates); err != nil {
return nil, fmt.Errorf("decoding response: %w", err)
}
return rates, nil
}
func main() {
client := NewClient("era_live_YOUR_API_KEY")
ctx := context.Background()
// Single pair
rates, err := client.GetRates(ctx, "USD", "EUR")
if err != nil {
panic(err)
}
fmt.Printf("1 USD = %.4f EUR\n", rates[0].Rate)
// Multiple targets
multiRates, err := client.GetRates(ctx, "USD", "EUR,GBP,JPY")
if err != nil {
panic(err)
}
for _, r := range multiRates {
fmt.Printf("1 USD = %.4f %s\n", r.Rate, r.Target)
}
}
For a quick one-off script, you can skip the client struct and parse the JSON into a raw interface.
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
req, _ := http.NewRequest("GET",
"https://exchange-rateapi.com/api/v1/rates?source=USD&target=EUR", nil)
req.Header.Set("Authorization", "Bearer era_live_YOUR_API_KEY")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
[
{
"rate": 0.9215,
"source": "USD",
"target": "EUR",
"time": "2026-05-15T12:00:00Z"
}
]
[
{ "rate": 0.9215, "source": "USD", "target": "EUR", "time": "2026-05-15T12:00:00Z" },
{ "rate": 0.7891, "source": "USD", "target": "GBP", "time": "2026-05-15T12:00:00Z" },
{ "rate": 151.42, "source": "USD", "target": "JPY", "time": "2026-05-15T12:00:00Z" }
]
net/http for HTTP requests and encoding/json for JSON parsing. No third-party packages required.
Get your free API key and start fetching exchange rates in Go in under a minute.
Get Free API Key →