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

Go调用API无法读取完整响应体导致JSON解析失败问题求助

问题根因
  • 主动丢弃读响应错误:代码中body, _ := ioutil.ReadAll(resp.Body)使用_忽略了读取操作的所有报错,网络波动、连接提前断开、服务端中断传输等异常都会被掩盖,最终仅能拿到不完整的响应字节
  • HTTP客户端无超时限制:零值初始化的http.Client{}未配置任何超时阈值,弱网或服务端异常时连接中断不会触发错误回调,ReadAll会直接返回当前已读取的部分内容
  • 潜在服务端/代理问题:可额外校验响应头的Content-Length值是否和实际读取的字节长度一致,部分反向代理配置异常可能会主动截断响应内容
修复方案
  1. 禁止忽略所有操作的返回错误,读取响应、JSON解析环节的错误必须捕获处理
  2. 给HTTP客户端配置合理的超时时间,避免无限等待异常连接
  3. 可直接使用json.Decoder从响应流直接解码,减少中间字节处理环节,也可以读取完成后校验Content-Length确保响应完整

修复后代码示例

var reqBody = []byte(fmt.Sprintf(`{
    "methodName": "GetPropertyList",
    "params": {
        "token_key": "%v",
        "token_secret": "%v"
    }
}`, token, secret))

req, err := http.NewRequest("POST", proxy_url, bytes.NewBuffer(reqBody))
if err != nil {
    log.Printf("创建请求失败: %v", err)
    return
}
req.Header.Set("Content-Type", "application/json")

// 配置客户端超时,可根据业务调整时长
client := http.Client{
    Timeout: 30 * time.Second,
}
  
resp, err := client.Do(req)
if err != nil {
    log.Printf("发起请求失败: %v", err)
    return
}
defer resp.Body.Close()

// 方案1:先读全再解析,保留错误检查
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
    log.Printf("读取响应失败: %v", err)
    return
}
log.Printf("BODY长度: %d,预期长度: %s", len(body), resp.Header.Get("Content-Length"))

var respModel ResponseModel
err = json.Unmarshal(body, &respModel)
if err != nil {
    log.Printf("JSON解析失败,响应内容: %s,错误: %v", string(body), err)
    return
}

// 方案2:直接用Decoder从流解析,代码更简洁
// var respModel ResponseModel
// err = json.NewDecoder(resp.Body).Decode(&respModel)
// if err != nil {
//     log.Printf("响应解析失败: %v", err)
//     return
// }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 17:15:03