
Go 标准库 net/http 在执行 http.Get 等默认请求时,会自动添加 User-Agent: Go-http-client/1.1 和 Accept-Encoding: gzip 两个基础请求头,不发送其他默认头;如需自定义(如绕过服务端 UA 检查或设置认证),必须显式配置 http.Request。
go 标准库 `net/http` 在执行 `http.get` 等默认请求时,会自动添加 `user-agent: go-http-client/1.1` 和 `accept-encoding: gzip` 两个基础请求头,不发送其他默认头;如需自定义(如绕过服务端 ua 检查或设置认证),必须显式配置 `http.request`。
在 Go 中,使用 http.Get(url) 或 http.Post(url, ...) 等便捷函数发起 HTTP 请求时,底层会自动构造一个 *http.Request 并通过默认的 http.DefaultClient 发送。此时,Go 会自动注入以下两个标准请求头:
- User-Agent: Go-http-client/1.1
- Accept-Encoding: gzip
✅ 这是仅有的两个默认头——Go 不会像某些语言(如 Python 的 urllib 附带 Python-urllib/3.4)那样添加额外标识性头,也不会默认设置 Accept、Content-Type、Connection 或 Host(后者由 http.Transport 自动填充,不属于用户可见的请求头字段)。
⚠️ 注意:Host 头虽必然存在,但由 net/http 在发送前自动根据 URL 填充,不属于“用户设置”或“默认添加”的请求头范畴;同理,Content-Length(对无 body 的 GET)或 Transfer-Encoding 等由底层自动计算,不可见且不应手动覆盖。
示例:验证默认请求头
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
req, err := http.NewRequest("GET", "https://httpbin.org/headers", nil)
if err != nil {
log.Fatal(err)
}
// 使用默认 client 发送(不修改 req.Header)
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Printf("%s\n", body) // 输出类似:{"headers":{"User-Agent":"Go-http-client/1.1","Accept-Encoding":"gzip"}}
}
如何自定义请求头?
若需替换 User-Agent、添加认证 Token 或设置 Accept 类型,应显式操作 req.Header:
req.Header.Set("User-Agent", "MyApp/1.0")
req.Header.Set("Authorization", "Bearer abc123")
req.Header.Set("Accept", "application/json")
? 关键提醒:
- *切勿在 http.Get 后修改其返回的 `http.Response.Request.Header** —— 此时请求已发出,修改无效;必须在http.NewRequest后、Do()` 前设置。
- 若使用 http.Client 自定义超时或 Transport,也需确保在构造 *http.Request 阶段完成头设置。
- 生产环境调用外部 API 时,建议显式设置 User-Agent(符合 RFC 7231),既便于服务端统计,也避免被部分 API 拒绝(如 GitHub API 要求合法 UA)。
总之,Go 的设计哲学是「显式优于隐式」:默认头极少,灵活性高,但所有关键行为(包括头管理)均由开发者精确控制——这是其健壮性与可维护性的基石。











