You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

首次使用Go调用股票API,多ticker请求返回体被截断求助

多Ticker股票API返回解析不全问题的解决方案

核心问题

你的JSON解析中途失败,导致看起来返回体被截断,实际原因是:

  • ResponseData结构体中ExchangeShort、ExchangeLong被定义为bool类型,但API返回的是null,Go的基础类型bool无法解析JSON的null值,解析到第二个对象时触发错误,终止了解析流程。
  • MarketCap字段同样被定义为float64,但API返回null,也会导致解析失败。
  • PreviousCloseTime的JSON标签与API返回的键名不匹配(API返回previous_close_price_time,但标签写的是previous_close_time)。

修复步骤

  1. 修正结构体字段类型:将接受null的字段改为指针类型,允许解析null值。
  2. 修正JSON标签:确保标签与API返回的键名完全一致。
  3. 完善错误处理:不要忽略任何错误,便于排查问题。

修改后的结构体定义

import "time"

type Stock struct {
    Name               string  `json:"name"`
    Ticker             string  `json:"ticker"`
    Price              float64 `json:"price"`
    DayHigh            float64 `json:"day_high"`
    DayLow             float64 `json:"day_low"`
    DayOpen            float64 `json:"day_open"`
    DayChange          float64 `json:"day_change"`
    PreviousClosePrice float64 `json:"previous_close_price"`
}

type ApiResponseStockData struct {
    ResponseStockData []ResponseData `json:"data"`
}

type ResponseData struct {
    Name                 string     `json:"name"`
    Ticker               string     `json:"ticker"`
    ExchangeShort        *bool      `json:"exchange_short"`  // 改为指针类型,支持null
    ExchangeLong         *bool      `json:"exchange_long"`   // 改为指针类型,支持null
    MicCode              string     `json:"mic_code"`
    Currency             string     `json:"currency"`
    Price                float64    `json:"price"`
    DayHigh              float64    `json:"day_high"`
    DayLow               float64    `json:"day_low"`
    DayOpen              float64    `json:"day_open"`
    DayChange            float64    `json:"day_change"`
    YearHigh             float64    `json:"52_week_high"`
    YearLow              float64    `json:"52_week_low"`
    MarketCap            *float64   `json:"market_cap"`      // 改为指针类型,支持null
    PreviousClosePrice   float64    `json:"previous_close_price"`
    PreviousCloseTime    time.Time  `json:"previous_close_price_time"` // 修正标签匹配API键名
    Volume               float64    `json:"volume"`
    IsExtendedHoursPrice bool       `json:"is_extended_hours_price"`
    LastTradeTime        time.Time  `json:"last_trade_time"`
}

修改后的请求解析函数

import (
    "fmt"
    "io"
    "net/http"
    "net/url"
    "encoding/json"
)

func getStockPriceData(ticker string) ([]Stock, error) {
    baseURL, err := url.Parse("https://api.stockdata.org")
    if err != nil {
        return nil, fmt.Errorf("解析基础URL失败: %w", err)
    }

    baseURL.Path += "/v1/data/quote" // 补充斜杠,避免路径拼接错误

    params := url.Values{}
    params.Add("symbols", ticker)
    params.Add("api_token", apiToken.ApiToken)

    baseURL.RawQuery = params.Encode()

    req, err := http.NewRequest("GET", baseURL.String(), nil)
    if err != nil {
        return nil, fmt.Errorf("创建请求失败: %w", err)
    }

    res, err := http.DefaultClient.Do(req)
    if err != nil {
        return nil, fmt.Errorf("发送请求失败: %w", err)
    }
    defer res.Body.Close()

    // 检查响应状态码,排除API错误
    if res.StatusCode < 200 || res.StatusCode >= 300 {
        return nil, fmt.Errorf("API返回错误状态码: %s", res.Status)
    }

    body, err := io.ReadAll(res.Body)
    if err != nil {
        return nil, fmt.Errorf("读取响应体失败: %w", err)
    }

    apiResponseData := ApiResponseStockData{}
    err = json.Unmarshal(body, &apiResponseData)
    if err != nil {
        return nil, fmt.Errorf("解析JSON失败: %w", err)
    }

    stocks := []Stock{}
    for _, data := range apiResponseData.ResponseStockData {
        stock := Stock{
            Name:               data.Name,
            Ticker:             data.Ticker,
            Price:              data.Price,
            DayHigh:            data.DayHigh,
            DayLow:             data.DayLow,
            DayOpen:            data.DayOpen,
            PreviousClosePrice: data.PreviousClosePrice,
            DayChange:          data.DayChange,
        }
        stocks = append(stocks, stock)
    }
    return stocks, nil
}

额外说明

  • 指针类型在Go中可以接受JSON的null值,解析时会将null转换为nil。
  • 完善错误处理后,后续遇到问题可以直接通过错误信息定位原因,避免像之前一样忽略错误导致排查困难。
  • 路径拼接时补充斜杠是为了避免出现https://api.stockdata.orgv1/data/quote这类错误URL。

内容的提问来源于stack exchange,提问作者Niall

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 10:09:53