用 http.newrequest 创建请求后,通过 req.header.set 或 req.header.add 设置自定义 header;set 覆盖同名字段,add 支持多值;必须在 http.defaultclient.do(req) 前设置,且每次请求应新建 *http.request 实例,不可复用。

怎么用 http.NewRequest 设置自定义 Header
直接在请求对象上写,不是传参也不是配置。创建完 *http.Request 后,用 req.Header.Set 或 req.Header.Add 写入字段。
常见错误是:先调用 http.Get 或 http.Post 这类快捷函数,再想改 Header——它们返回的是已发出的响应,Response.Request.Header 是只读副本,改了也没用。
-
Set会覆盖同名字段(比如两次Set("User-Agent", "a"),第二次生效) -
Add允许同名多值(如Cookie需要多个键值对时用它) - 必须在调用
http.DefaultClient.Do(req)前设置,之后改无效
req, _ := http.NewRequest("GET", "https://api.example.com", nil)
req.Header.Set("Authorization", "Bearer token123")
req.Header.Add("Cookie", "sid=abc")
req.Header.Set("User-Agent", "my-app/1.0")
resp, _ := http.DefaultClient.Do(req)
为什么 http.Post 不能设 Header
因为 http.Post 是封装好的“发完就扔”函数,内部新建请求、设置 Content-Type、调用 Do,没留出口给你插手 Header。
它只适合最简单的表单提交或 JSON 推送,且你接受它的默认行为:比如自动加 Content-Type: application/x-www-form-urlencoded,但如果你需要 application/json 或带认证头,它就不够用。
- 想设 Header 就别用
http.Post,改用http.NewRequest+http.DefaultClient.Do -
http.PostForm同理,只支持url.Values,不支持自定义头 - 如果只是换
Content-Type,http.Post的第三个参数是io.Reader,你可以自己序列化并手动设头——但这时不如直接用NewRequest
Content-Type 设错导致后端解析失败
后端按 Content-Type 决定怎么解包 body,设错等于告诉对方“我发的是 JSON”,实际发的是裸字符串,结果 400 或空数据。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
典型场景:发 JSON 时漏设 Content-Type: application/json,或者设成了 text/plain;发表单时用了 application/json 却传 url.Values。
- JSON 请求:body 用
json.Marshal,Header 必须Set("Content-Type", "application/json") - 表单请求:用
url.Values{"key": {"val"}}.Encode(),Header 设"application/x-www-form-urlencoded" - 上传文件:用
multipart.Writer,Header 由它自动生成multipart/form-data; boundary=...,别手动覆盖
客户端复用与 Header 污染风险
很多人把 req.Header 当成一次性的,其实不是:如果复用同一个 *http.Request 对象(比如循环里不新建),Header 会累积,上次的 Add 还在,下次又加一遍,可能触发后端限流或拒绝。
更隐蔽的是:http.NewRequest 内部会初始化一个空 Header,但不会清空你之前塞进去的值——所以别在循环外建 req、循环内只改 URL 或 body。
- 每次请求都应调用一次
http.NewRequest,不要复用*http.Request实例 - 如果要用连接池或自定义
http.Client,Header 污染和连接复用是两回事,Client 可复用,Request 不可复用 - 调试时打印
req.Header看一眼,比猜快得多:fmt.Printf("%+v\n", req.Header)
Header 看似简单,但它是请求发出前最后一道手动干预点,设错不报错、只让后端静默失败——最容易被忽略的就是“以为设了,其实没生效”,或者“以为只设一次,其实叠了三次”。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










