ใช้ standard library ของ Go ได้เลย ตรวจสอบสถานะ HTTP ก่อน decode JSON และเก็บ source, market_session และเวลาที่อัปเดตคู่กับอัตราแลกเปลี่ยน.
- สร้าง client แบบมี type: ใช้ net/http, context และ encoding/json ขอหลายสกุลเงินในครั้งเดียว และใส่ Bearer เมื่อมี EXCHANGERATE_API_KEY เท่านั้น.
- เรียกใช้พร้อม timeout: context.WithTimeout ป้องกัน connection ค้างนานเกินไป ใน production ให้ใช้ http.Client ร่วมกัน.
- จัดการ error และ freshness: 401 ต้องแก้คีย์ ส่วน 429 ต้องลดการเรียก เก็บ source, market_session, data_updated_at และอย่าใส่คีย์ใน browser หรือ mobile app.
สร้าง client แบบมี type
ใช้ net/http, context และ encoding/json ขอหลายสกุลเงินในครั้งเดียว และใส่ Bearer เมื่อมี EXCHANGERATE_API_KEY เท่านั้น.
package mainimport ( "context" "encoding/json" "fmt" "net/http" "log" "os" "regexp" "strings" "time")type Latest struct { Base string `json:"base"` Source string `json:"source"` MarketSession string `json:"market_session"` UpdatedAt time.Time `json:"data_updated_at"` Sources map[string]string `json:"sources"` EffectiveAt map[string]string `json:"effective_at"` Rates map[string]json.Number `json:"rates"`}func LatestRates(ctx context.Context, base string) (Latest, error) { base = strings.ToUpper(base) if !regexp.MustCompile("^[A-Z]{3}$").MatchString(base) { return Latest{}, fmt.Errorf("invalid base currency: %q", base) } url := "https://api.exchangerate.dev/v1/latest/" + base + "?symbols=EUR,GBP,JPY" req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { return Latest{}, err } if key := os.Getenv("EXCHANGERATE_API_KEY"); key != "" { req.Header.Set("Authorization", "Bearer "+key) } client := &http.Client{Timeout: 5 * time.Second, CheckRedirect: func(_ *http.Request, _ []*http.Request) error { return http.ErrUseLastResponse }} res, err := client.Do(req) if err != nil { return Latest{}, err } defer res.Body.Close() if res.StatusCode < 200 || res.StatusCode >= 300 { return Latest{}, fmt.Errorf("exchange rate API: HTTP %s", res.Status) } var out Latest if err := json.NewDecoder(res.Body).Decode(&out); err != nil { return Latest{}, err } return out, nil}func main() { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() latest, err := LatestRates(ctx, "USD") if err != nil { log.Fatal(err) } fmt.Println(latest.Rates["EUR"], latest.Sources["EUR"], latest.EffectiveAt["EUR"])}เรียกใช้พร้อม timeout
go run main.goจัดการ error และ freshness
401 ต้องแก้คีย์ ส่วน 429 ต้องลดการเรียก เก็บ source, market_session, data_updated_at และอย่าใส่คีย์ใน browser หรือ mobile app.
รายงานรายวันใช้วันละครั้ง ส่วน dashboard อาจใช้ทุกชั่วโมง เมื่อเจอ 429 ให้ลดความถี่ ไม่ใช่สร้าง retry ทันที.
- เก็บอัตราพร้อม source และเวลา.
- ใช้กับ automation และการวิเคราะห์.
- อย่าใช้เป็นราคาที่ execute ได้.