go处理http响应必须手动关闭resp.body并检查statuscode:不关会导致连接池阻塞和文件描述符耗尽;不查状态码会忽略404/500等业务错误;content-type须以响应头为准,不可硬猜编码。

Go 处理 HTTP 响应,核心就三件事:别漏关 resp.Body、别跳过 StatusCode 检查、别硬猜 Content-Type。少做一步,轻则数据错乱,重则连接耗尽、服务假死。
为什么必须手动调用 resp.Body.Close()
Go 的 http.Client 不会自动关闭响应体——它把责任交给你。不关,TCP 连接就卡在连接池里,下次复用时可能读到上一次的残留数据;更严重的是,文件描述符持续增长,最终触发 too many open files 错误,整个服务夯住。
- 错误写法:
body, _ := io.ReadAll(resp.Body)后直接结束,没关 - 正确姿势:在
err == nil分支开头立刻加defer resp.Body.Close()(注意:resp为nil时不能 defer) - 即使你用
json.NewDecoder(resp.Body).Decode(&v)流式解析,也得关——它不负责关 - 如果后续要多次读取 body(极少见),得先用
io.ReadAll拷贝出来,再重新构造bytes.NewReader
怎么判断响应算“成功”而不是只看 err == nil
http.Get 或 client.Do 的 err 只管网络层(连不上、超时、TLS失败等),不管业务逻辑。404、500、422 全都返回 err == nil,但 resp.StatusCode 已经不是你想的那样了。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
- 别写
if err != nil就完事——这只能捕获连接失败,漏掉全部 HTTP 错误码 - 必须显式检查:
if resp.StatusCode = 300,或更常见地用resp.StatusCode >= 400 - 非 2xx 响应体往往含错误详情(如
{"error": "invalid_token"}),建议读出来并包装进自定义 error - 重定向(301/302)默认自动跟随,若需拦截,得配
CheckRedirect;304 响应体为空,但头里有缓存信息,别直接ReadAll报 panic
怎么安全解析 resp.Body 而不崩在编码或格式上
响应头里的 Content-Type 是唯一可信依据。别假设是 UTF-8,也别靠 string(bodyBytes) 硬转——BOM、GBK、ISO-8859-1 都可能真实存在。
- 先取头:
ct := resp.Header.Get("Content-Type"),再按类型分支处理 - JSON:
json.Unmarshal(bodyBytes, &v),结构体字段加json:"field_name"标签;若不确定结构,用map[string]interface{},但访问前必须类型断言 - 表单:
url.ParseQuery(string(bodyBytes)),注意 Content-Type 必须是application/x-www-form-urlencoded - 纯文本或 HTML:用
golang.org/x/text/encoding检测实际编码,再转换;别信charset=utf-8声明 - 大响应防 OOM:用
io.LimitReader(resp.Body, 10*1024*1024)限 10MB,再传给json.NewDecoder流式解码
最常被跳过的其实是状态码检查和 Body 关闭这两步——它们不出现在编译错误里,也不报 panic,只在高并发或异常响应时悄悄拖垮服务。写完请求逻辑,花三秒确认这两行有没有:一行是 if resp.StatusCode >= 400,一行是 defer resp.Body.Close()。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










