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

Go语言中GET请求外部API时如何强制获取JSON响应?

解决Go请求API时压测出现JSON解析错误的问题

这个坑我之前踩过!压测时服务器扛不住返回了HTML错误页(比如500、503这类状态码对应的错误页面),你的代码直接把它当JSON解析,就会出现invalid character '<' looking for beginning of value这个错误。咱们来一步步修复:

核心问题分析

你代码里有两个关键错误:

  1. 错误设置响应头:resp.Header.Set("Content-Type", contentType)是在修改服务器返回的响应头,这完全没用!服务器不会因为你改了响应头就返回JSON,你需要在发送请求时告诉服务器你只接受JSON格式。
  2. 没检查响应状态码:压测时服务器很可能因为过载返回非2xx的状态码(比如500),这时返回的是HTML错误页,你直接去解析JSON肯定失败。

修复后的代码示例

1. 重构Request函数,正确设置请求头并检查状态码

import (
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)

func Request(url string, acceptType string) ([]byte, error) {
    // 创建GET请求,而非直接用http.Get,这样可以自定义请求头
    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        return nil, fmt.Errorf("创建请求失败: %w", err)
    }

    // 设置Accept请求头,明确告诉服务器我们只接受JSON响应
    req.Header.Set("Accept", acceptType)

    // 使用带超时的客户端,避免压测时请求挂起
    client := &http.Client{Timeout: 10 * time.Second}
    resp, err := client.Do(req)
    if err != nil {
        return nil, fmt.Errorf("请求发送失败: %w", err)
    }
    defer resp.Body.Close() // 用defer确保响应体被关闭,避免资源泄漏

    // 先检查响应状态码,非2xx直接返回错误,同时带上错误内容方便调试
    if resp.StatusCode < 200 || resp.StatusCode >= 300 {
        errorBody, _ := ioutil.ReadAll(resp.Body)
        return nil, fmt.Errorf("意外状态码 %d: %s", resp.StatusCode, string(errorBody))
    }

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

    return body, nil
}

2. 修改调用逻辑,优雅处理错误

url := fmt.Sprintf("https://example.com/api/category/%s", category)
acceptType := "application/json"

body, err := Request(url, acceptType)
if err != nil {
    // 压测时不要直接Fatal退出,记录日志后继续处理其他请求
    log.Printf("请求出错: %v", err)
    return // 或者根据业务逻辑做重试/跳过
}

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

额外优化建议

  • 增加重试逻辑:对5xx类的服务器错误,可以做有限次数的重试,但要注意间隔时间,避免给服务器增加额外负担。
  • 限制并发数:压测时如果并发太高,服务器更容易崩溃,你可以在http.Client的Transport中设置最大并发连接数。
  • 监控响应内容:压测时可以偶尔打印响应内容,确认服务器确实返回了符合预期的JSON格式数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:55:37