http.get 仅适用于调试,生产环境必须用自定义 http.client 配置超时、复用连接、设置 header;get 参数需用 url.values 安全编码;务必关闭 resp.body 并检查 statuscode。

用 http.Get 发最简 GET 请求,但别直接用在生产环境
它确实能发请求,但默认不设超时、不复用连接、不处理重定向边界,线上一压就挂。http.Get 底层调用了 http.DefaultClient.Do,而 http.DefaultClient 的 Timeout 是 0(无限等待),Transport 也用默认配置,没开连接池复用。
- 开发调试时快速试 API 可以用:
resp, err := http.Get("https://api.example.com/v1/status") - 必须手动关响应体:
defer resp.Body.Close(),否则连接永远不释放 - 遇到 4xx/5xx 状态码,
err仍是nil,得自己检查resp.StatusCode - 不支持设置
User-Agent、Authorization等头,得换http.NewRequest+http.Client.Do
带超时和自定义 Header 的标准写法
真正可控的 GET,得自己构造 http.Request,再用带配置的 http.Client 发。核心是控制超时、复用连接、显式设头。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 超时必须设:用
context.WithTimeout包装请求上下文,比只设Client.Timeout更可靠(能中断 DNS 解析、TLS 握手) - Header 要在
req.Header.Set,不是req.Header.Add(后者会重复添加,某些服务拒收) -
http.Client实例建议复用,不要每次请求都 new 一个,否则Transport连接池失效 - 示例片段:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() req, _ := http.NewRequestWithContext(ctx, "GET", "https://api.example.com/data", nil) req.Header.Set("User-Agent", "my-app/1.0") client := &http.Client{} resp, err := client.Do(req)
GET 带 query 参数,别拼字符串
手拼 URL 容易漏编码,比如空格变 +、中文变乱码、特殊字符触发 400。Go 提供了 url.Values 和 url.ParseQuery,专治这个。
- 构建参数用
url.Values{"key": []string{"value"}},然后调用Encode()得到安全的 query 字符串 - 完整拼接示例:
u, _ := url.Parse("https://api.example.com/search") q := u.Query() q.Set("q", "golang http") q.Set("page", "1") u.RawQuery = q.Encode() resp, _ := http.Get(u.String()) - 如果参数值来自用户输入,
url.QueryEscape不够用,必须走url.Values流程,它内部调用的是更严格的url.PathEscape变体 - 注意:
url.ParseQuery解析的是 query string(如"a=1&b=2"),不是完整 URL;解析完整 URL 用url.Parse
常见错误:403 Forbidden 或 connection refused
这两个错误看起来像服务端问题,但大概率是客户端配置或网络层没对上。
-
403 Forbidden:多数是没设User-Agent,被 CDN 或 WAF 拦了;也可能是 Host 头不匹配(比如请求https://api.example.com却没设Host: api.example.com) -
connection refused:本地防火墙、代理设置干扰;或目标服务只监听localhost,你却用127.0.0.1(IPv4 vs IPv6 解析差异有时会导致这个) - 调试时加日志:
log.Printf("req.URL: %+v, req.Host: %s, req.Header: %+v", req.URL, req.Host, req.Header) - DNS 缓存可能卡住:如果改了 hosts 或切了环境,记得清
http.Transport的 DNS 缓存,或临时设transport.DialContext = net.DefaultResolver.DialContext
resp.Body 关闭时机和上下文超时的嵌套层级——比如外层函数传进来的 ctx 已经 cancel,你还拿它去发请求,结果 Do 直接返回 context.Canceled,而不是网络错误。golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










