Go中HTTP Header是map[string][]string,Request只读、Response可写且需在WriteHeader前设置;键名自动标准化;Cookie推荐http.SetCookie;敏感头需过滤日志。

在 Go 的 net/http 包中,HTTP 头信息通过 Header 字段管理,它本质是一个 map[string][]string。Request 和 Response 都有 Header 字段,但使用方式和注意事项略有不同——关键在于:Request 的 Header 是只读的(需用 ParseForm 或 ParseMultipartForm 后才能安全读取表单头),而 Response 的 Header 可直接写;且所有 Header 键名会自动标准化(如 content-type → Content-Type)。
设置 Response Header 的常用方式
Response Header 应在调用 WriteHeader() 或首次调用 Write() 之前设置,否则可能被忽略或触发默认状态码(200)并锁定 Header。
-
添加单个值(覆盖已有):用
w.Header().Set("X-App-Version", "1.2.0") -
追加多个值(不覆盖):用
w.Header().Add("Set-Cookie", "session=abc; HttpOnly") -
删除某个头:用
w.Header().Del("X-Debug") -
设置 Content-Type 推荐用快捷方法:直接调用
w.Header().Set("Content-Type", "application/json; charset=utf-8"),或更稳妥地用w.Header().Set("Content-Type", "text/html; charset=utf-8"),避免依赖WriteHeader自动推断
读取 Request Header 的注意事项
Request Header 是只读映射,不能直接修改(修改无效)。你可以安全读取,但需注意:
- Header 键名自动标准化,
r.Header.Get("user-agent")和r.Header.Get("User-Agent")效果相同 - 敏感头(如
Authorization、Cookies)需显式处理:r.Header.Get("Authorization")或解析r.Cookies() - 不要在中间件中试图改写
r.Header来“伪造”请求头——应使用自定义上下文(context.WithValue)或封装新 Request - 若需修改请求头再转发(如反向代理场景),应新建
*http.Request并复制所需 Header,例如:newReq.Header = r.Header.Clone()(Go 1.19+ 支持Clone())
常见易错点与最佳实践
Header 看似简单,但几个细节常导致调试困难:
立即学习“go语言免费学习笔记(深入)”;
-
不要在 Write 之后再 Set Header:一旦响应体开始写入(
w.Write([]byte{...})),Header 就被提交,后续Set无效,也不会报错 -
Cookie 不要混用 Header.Set 和 http.SetCookie:后者会自动编码、处理过期时间、Domain/Path 等,推荐优先用
http.SetCookie(w, &http.Cookie{...}) -
自定义 Header 命名建议用 X- 前缀(如
X-Request-ID)或遵循 RFC 标准(如Retry-After),避免与未来标准冲突 -
日志中打印 Header 时记得过滤敏感字段,比如
Authorization、Cookie,防止泄露凭据
基本上就这些。Header 管理本身不复杂,但时机和所有权容易忽略——记住:Response Header 要早设、别晚写;Request Header 要只读、别硬改;转发时用 Clone() 更安全。










