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

Go中API Handler调用第三方API后无法返回响应问题

问题分析与修复方案

1. 未正确关闭外部API响应的Body

在GetEvents方法中,调用o.client.Do(req)获取到resp后,既没有关闭resp.Body,也没有读取其中内容。Go的HTTP客户端依赖连接池复用连接,若不关闭响应Body,连接会被长期占用,最终导致连接池耗尽,后续向客户端发送响应时无法获取可用连接,表现为客户端收不到返回内容。

修复代码:

func (o *API) GetEvents(account string, startDate string, endDate string) ([]Event, error) {
    BaseUrl := "http://external-api.com"
    url := fmt.Sprintf("%s/v2/client/%s/event?startDate=%s&endDate=%s", BaseUrl, account, startDate, endDate)
    // 不要忽略请求创建错误
    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        return nil, err
    }
    // 确保结构体字段名大小写匹配(此处假设结构体字段为小写token/secret)
    req.Header.Add("token", o.token)
    req.Header.Add("secret", o.secret)

    resp, err := o.client.Do(req)
    if err != nil {
        return nil, err
    }
    // 必须延迟关闭响应Body
    defer resp.Body.Close()

    // 即使不需要响应内容,也要读取Body避免连接泄漏
    _, err = io.Copy(io.Discard, resp.Body)
    if err != nil {
        return nil, err
    }

    // 检查外部API响应状态码
    if resp.StatusCode != http.StatusOK {
        return nil, fmt.Errorf("external API returned status: %s", resp.Status)
    }

    fmt.Println(resp)
    return []Event{}, nil
}

2. 忽略关键错误

原代码中http.NewRequest的错误被直接忽略(用_接收),若URL格式非法(比如account包含未转义的特殊字符),会导致请求失败但无法排查。必须显式处理该错误。

3. 结构体字段访问不匹配(潜在问题)

如果API结构体中的token/secret字段定义为小写(token string),但GetEvents中误写为o.Token(大写),会导致请求头中的认证信息为空,外部API可能返回错误响应。需确保字段名大小写完全一致。

4. 未校验外部API响应状态

即使client.Do()没有返回错误,外部API仍可能返回非200状态码(如401权限错误、404资源不存在),此时继续执行后续逻辑不符合预期,需添加状态码校验。

5. 强化sendJSON的错误处理

虽然你反馈未看到错误,但可以优化日志输出和异常处理,避免因Header已写入导致的错误:

func sendJSON(w http.ResponseWriter, status int, message string, data interface{}) {
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(status)
    err := json.NewEncoder(w).Encode(&APIResponse{
        Status:  status,
        Message: message,
        Data:    data,
    })
    if err != nil {
        // 使用标准日志库替代fmt.Println,便于排查问题
        log.Printf("failed to encode response: %v", err)
        // 若已写入Header,直接输出错误JSON
        w.Write([]byte(fmt.Sprintf(`{"status":500,"message":"%s"}`, err.Error())))
        return
    }
}

验证步骤

修复后重新运行服务:

  1. 确认GetEvents中正确关闭并读取了外部API的响应Body
  2. 检查服务端日志,确认sendJSON正常执行且无编码错误
  3. 验证外部API返回状态码为200

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 19:13:28