http.post仅适合调试脚本,因其强制设application/x-www-form-urlencoded、无法设认证头/超时/复用连接;生产环境必须用http.newrequest+显式配置的http.client。

别用 http.Post 发带认证、JSON 或文件的请求——它会强制设 Content-Type: application/x-www-form-urlencoded,且无法控制超时、复用连接或加自定义 header。
http.Post 为什么只适合调试脚本
http.Post 看似一行搞定,但底层每次新建 http.Client,不复用 TCP 连接;它把第三个参数(io.Reader)直接塞进 body,然后硬编码 Content-Type,不管你要发的是 JSON、XML 还是二进制流。
- 常见错误现象:
415 Unsupported Media Type,因为服务端等application/json,而它发了application/x-www-form-urlencoded - 中文或特殊字符(如
&、=)在表单场景下会乱码——它不做 URL 编码,你得自己拼"name=%E4%BD%A0&age=25",极易出错 - 无法设
Authorization、User-Agent等 header,也不能配Timeout - 只适合这种场景:本地快速测一个登录接口,且服务端明确接受
application/x-www-form-urlencoded格式
http.NewRequest + Do 是生产环境唯一靠谱写法
真正可控的 POST 必须用 http.NewRequest 构造请求,再交由显式配置的 http.Client 执行。这一步才能决定 body 怎么读、header 怎么设、超时怎么控。
-
req.Header.Set("Content-Type", "...")必须手动调用——http.NewRequest不设默认值 - body 参数必须是
io.Reader:JSON 用bytes.NewReader(jsonBytes),字符串用strings.NewReader("..."),别传裸字符串 - 超时必须配在
http.Client上,比如&http.Client{Timeout: 10 * time.Second};用http.DefaultClient没超时,容易卡死 - 哪怕只读
resp.StatusCode,也得调defer resp.Body.Close(),否则连接无法复用,高并发下直接耗尽 fd
发 JSON 和发表单数据的关键区别
两者 body 构造和编码逻辑完全不同,混用就会 400 或解析失败。
- 发 JSON:
json.Marshal得到字节切片 → 用bytes.NewReader包一层 → 设Content-Type: application/json - 发表单(
application/x-www-form-urlencoded):url.Values{"name": []string{"foo"}, "age": []string{"25"}}→ 调.Encode()→ 用strings.NewReader包 → 设对应Content-Type - 别手写
"name=foo&age=25":URL 编码不是可选项,url.Values自动处理中文、空格、&等,比strings.ReplaceAll可靠十倍
文件上传必须用 mime/multipart,别手拼 boundary
multipart/form-data 的 boundary 规则严格:换行符必须是 \r\n,boundary 字符串不能出现在原始内容里,且结尾要双减号。手拼极易格式错误,服务端直接拒收。
- 正确做法:用
multipart.Writer,它自动选随机 boundary、处理换行、写分隔符、封尾 - 示例关键步骤:
w := multipart.NewWriter(tmp)→w.WriteField("key", "value")→w.CreateFormFile("file", "a.txt")→w.Close()→ 设Content-Type: multipart/form-data; boundary=xxx(w.FormDataContentType()返回完整值) - 别忘了把
w的输出作为 body 传给http.NewRequest
最常被忽略的一点:无论用哪种方式发 POST,只要没读完 resp.Body 或没调 Close(),连接就卡在 keep-alive 状态,后续请求可能阻塞或超时。这不是 bug,是 Go 的显式资源管理设计——它不会替你猜你还要不要读响应体。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











