func FetchRates() ([]CountryRates, error) {
	client := http.Client{
		Timeout: (time.Duration(ServiceTimeout) * time.Second),
	}
	r, err := client.Get("https://raw.githubusercontent.com/ibericode/vat-rates/master/vat-rates.json")
	if err != nil {
		return nil, err
	}
	apiResponse := &struct {
		Details string
		Version float32
		Items   map[string][]struct {
			EffectiveFrom string `json:"effective_from"`
			Rates         map[string]float32
		}
	}{}
	err = json.NewDecoder(r.Body).Decode(&apiResponse)
	if err != nil {
		return nil, err
	}
	rates := []CountryRates{}
	for code, periods := range apiResponse.Items {
		rate := CountryRates{CountryCode: code}
		for _, period := range periods {
			from := strings.Replace(period.EffectiveFrom, "0000-", "2000-", 1)
			fromTime, _ := time.Parse("2006-01-02", from)
			rperiod := RatePeriod{
				EffectiveFrom: fromTime,
				Rates:         period.Rates,
			}
			rate.Periods = append(rate.Periods, rperiod)
		}
		rates = append(rates, rate)
	}
	return rates, err
}
FetchRates fetches the latest VAT rates from ibericode/vat-rates and updates the in-memory rates
package vat
import (
	"encoding/json"
	"errors"
	"net/http"
	"strings"
	"sync"
	"time"
)
type RatePeriod struct {
	EffectiveFrom time.Time
	Rates         map[string]float32
}
type CountryRates struct {
	CountryCode string `json:"country_code"`
	Periods     []RatePeriod
}
var mutex = &sync.Mutex{}  
var countriesRates []CountryRates
var ErrInvalidCountryCode = errors.New("vat: unknown country code")
var ErrInvalidRateLevel = errors.New("vat: unknown rate level")
func (cr *CountryRates) GetRateOn(t time.Time, level string) (float32, error) {
	var activePeriod RatePeriod
	for _, p := range cr.Periods {
		if t.After(p.EffectiveFrom) && (activePeriod.EffectiveFrom.IsZero() || p.EffectiveFrom.After(activePeriod.EffectiveFrom)) {
			activePeriod = p
		}
	}
	activeRate, ok := activePeriod.Rates[level]
	if !ok {
		return 0.00, ErrInvalidRateLevel
	}
	return activeRate, nil
}
func (cr *CountryRates) GetRate(level string) (float32, error) {
	now := time.Now()
	return cr.GetRateOn(now, level)
}
func GetCountryRates(countryCode string) (CountryRates, error) {
	var rate CountryRates
	rates, err := GetRates()
	if err != nil {
		return rate, err
	}
	for _, r := range rates {
		if r.CountryCode == countryCode {
			return r, nil
		}
	}
	return rate, ErrInvalidCountryCode
}
func GetRates() ([]CountryRates, error) {
	var err error
	mutex.Lock()
	if countriesRates == nil {
		countriesRates, err = FetchRates()
	}
	mutex.Unlock()
	return countriesRates, err
}