http.Get不能用于生产环境,因其默认无超时(Timeout=0)、不复用连接、无法设Header、重定向不可控;必须用自定义*http.Client并配置Timeout、Transport连接池、CheckRedirect及url.Values编码参数。

http.Get 不能直接用于生产环境,它不设超时、不复用连接、不控制重定向,一卡就是几十秒挂起。
为什么 http.Get 在线上会卡住
默认的 http.DefaultClient 的 Timeout 是 0(无限等待),DNS 解析失败、服务端失联、中间网络抖动都会让 goroutine 永远阻塞。你看到的“请求没返回”,大概率是卡在 http.Get 内部的 dial 或 read 阶段。
- 不设超时:遇到慢服务或断连,goroutine 不释放
- 无连接复用:每次调用都新建 TCP 连接,文件描述符快速耗尽
- 无法设 Header:比如要传
Authorization或User-Agent,只能干瞪眼 - 重定向逻辑不可控:302 跳转可能绕到非预期域名,甚至死循环
发 GET 请求必须用自定义 *http.Client
真正可控的做法是显式构造 *http.Client,并配好关键参数:
-
Timeout:必须设,建议 5–10 秒,避免单请求拖垮整个 goroutine 池 -
Transport:至少确认MaxIdleConns和MaxIdleConnsPerHost不是 0(默认 100/100 够用) -
CheckRedirect:明确拒绝跳转或限制跳转次数,防意外外泄 - URL 参数用
url.Values编码,别用fmt.Sprintf拼接——中文、&、=会直接 400
示例:
立即学习“go语言免费学习笔记(深入)”;
values := url.Values{}
values.Set("q", "Go语言 HTTP")
u := &url.URL{
Scheme: "https",
Host: "api.example.com",
Path: "/search",
RawQuery: values.Encode(),
}
req, _ := http.NewRequest("GET", u.String(), nil)
client := &http.Client{Timeout: 8 * time.Second}
resp, err := client.Do(req)
if err != nil {
// 处理超时、连接失败等
}
defer resp.Body.Close() // 必须放在这里,哪怕 status 不是 200
POST JSON 为什么总返回 415
因为 http.Post 默认把 body 当作 application/x-www-form-urlencoded 发,即使你传的是 JSON 字节流,它也不会自动设 Content-Type: application/json。服务端一看 Content-Type 不对,直接拒收。
- 别用
http.Post(url, "application/json", body)—— 它设了 header,但底层仍用默认 client,没 timeout,不复用连接 - 正确路径:用
http.NewRequest构造,手动req.Header.Set("Content-Type", "application/json") -
body必须是io.Reader:用bytes.NewBuffer(jsonBytes)或strings.NewReader(string(jsonBytes)) -
json.Marshal可能返回 error,比如字段没加json:"field"tag,或含func/chan类型,不检查就 panic
漏关 resp.Body 是最隐蔽的资源泄漏
不是内存泄漏,而是连接池被占满:未关闭的 resp.Body 会让底层 TCP 连接无法归还给连接池,后续请求排队等待空闲连接,最终全部超时或阻塞。
-
defer resp.Body.Close()必须紧跟在client.Do(req)之后,不能放在if resp.StatusCode != 200分支里提前 return - 如果响应体很大,别直接
io.ReadAll,考虑io.LimitReader(resp.Body, 1<em>1024</em>1024)防爆内存 - 即使只读状态码或 header,也要关 Body;可用
io.Copy(io.Discard, resp.Body)快速丢弃 - 检查
resp.StatusCode:HTTP 错误码(如 401、503)不会触发err != nil,resp仍是有效指针,Body 里可能是错误页
真正的难点不在“怎么发”,而在“怎么稳住”——超时控制、连接复用、Body 关闭、Header 设置,四者缺一不可。线上跑几天不出事,不代表没问题;流量一上来,最先崩的就是 HTTP 客户端。


















