Go语言如何解析HTTP响应数组,获取第二个子数组的第二个元素?
Go解析Binance K线数据获取指定元素
方法一:直接解析为二维任意类型数组
Binance返回的K线是混合类型的二维数组(包含整数、字符串),可以直接用[][]interface{}解析,通过索引获取目标元素:
package main import ( "encoding/json" "fmt" "io/ioutil" "net/http" ) func main() { // 发起GET请求 response, err := http.Get("https://api.binance.com/api/v3/klines?symbol=ETHUSDT&interval=5m&limit=5") if err != nil { fmt.Println("请求失败:", err) return } // 确保响应体最终关闭 defer response.Body.Close() // 检查响应状态码是否正常 if response.StatusCode != http.StatusOK { fmt.Println("响应异常,状态码:", response.StatusCode) return } // 读取响应体内容 body, err := ioutil.ReadAll(response.Body) if err != nil { fmt.Println("读取响应体失败:", err) return } // 解析为二维任意类型数组 var klines [][]interface{} err = json.Unmarshal(body, &klines) if err != nil { fmt.Println("JSON解析失败:", err) return } // 校验数组长度是否满足需求 if len(klines) < 2 { fmt.Println("返回的K线数据不足2条") return } secondKline := klines[1] // 第二个子数组(索引从0开始) if len(secondKline) < 2 { fmt.Println("K线子数组元素数量不足") return } // 获取第二个子数组的第二个元素 targetElement := secondKline[1] fmt.Println("目标元素值:", targetElement) }
方法二:定义结构体实现类型安全解析
如果需要更清晰的类型管理,可以把K线的固定字段映射为结构体(Binance K线子数组顺序:时间戳、开盘价、最高价、最低价、收盘价、成交量、结束时间、成交额、成交笔数、主动买入成交量、主动买入成交额、忽略字段):
package main import ( "encoding/json" "fmt" "io/ioutil" "net/http" ) // Kline 对应Binance返回的单条K线数据结构 type Kline struct { OpenTime int64 // 数组第0位:开盘时间戳 OpenPrice string // 数组第1位:开盘价(用字符串避免浮点数精度丢失) HighPrice string LowPrice string ClosePrice string Volume string CloseTime int64 QuoteAssetVolume string NumberOfTrades int TakerBuyVolume string TakerBuyQuoteVolume string Ignore string } // UnmarshalJSON 自定义解析逻辑,将数组转为结构体 func (k *Kline) UnmarshalJSON(data []byte) error { var arr []interface{} if err := json.Unmarshal(data, &arr); err != nil { return err } if len(arr) < 12 { return fmt.Errorf("无效的K线数据长度") } k.OpenTime = int64(arr[0].(float64)) k.OpenPrice = arr[1].(string) k.HighPrice = arr[2].(string) k.LowPrice = arr[3].(string) k.ClosePrice = arr[4].(string) k.Volume = arr[5].(string) k.CloseTime = int64(arr[6].(float64)) k.QuoteAssetVolume = arr[7].(string) k.NumberOfTrades = int(arr[8].(float64)) k.TakerBuyVolume = arr[9].(string) k.TakerBuyQuoteVolume = arr[10].(string) k.Ignore = arr[11].(string) return nil } func main() { response, err := http.Get("https://api.binance.com/api/v3/klines?symbol=ETHUSDT&interval=5m&limit=5") if err != nil { fmt.Println("请求失败:", err) return } defer response.Body.Close() if response.StatusCode != http.StatusOK { fmt.Println("响应异常,状态码:", response.StatusCode) return } body, err := ioutil.ReadAll(response.Body) if err != nil { fmt.Println("读取响应体失败:", err) return } // 解析为Kline结构体数组 var klines []Kline err = json.Unmarshal(body, &klines) if err != nil { fmt.Println("JSON解析失败:", err) return } if len(klines) < 2 { fmt.Println("返回的K线数据不足2条") return } // 获取第二个K线的开盘价(对应子数组第二个元素) targetPrice := klines[1].OpenPrice fmt.Println("第二个K线的开盘价:", targetPrice) }
关键提示
- Go数组索引从0开始,第二个子数组对应索引1,子数组的第二个元素对应索引1
- 价格字段推荐用字符串存储,避免浮点数精度丢失
- 必须添加响应状态码检查、错误处理,避免程序意外崩溃
内容的提问来源于stack exchange,提问作者user2497209
相关产品推荐
相关产品推荐

