最稳妥的并发控制方式是用 goroutine + waitgroup 配合带缓冲的信号 channel(如 make(chan struct{}, n))限制并发数,避免资源耗尽或触发限流。

goroutine + WaitGroup 控制并发数量最稳妥
不加限制地开成百上千个 goroutine 发 HTTP 请求,轻则触发连接池耗尽、文件描述符超限,重则目标服务直接 429 或被拉入黑名单。用 sync.WaitGroup 配合固定数量的 worker 是实际项目里最可控的做法。
- 先用
make(chan struct{}, N)建一个带缓冲的信号 channel,N 就是最大并发数(比如 10) - 每个请求前
sem 占位,结束后 <code> 归还 -
WaitGroup只负责等所有请求启动完毕,别让它等响应——响应可能失败或超时,等它反而卡死 - 别把
http.DefaultClient直接扔进高并发场景;显式配置Timeout和Transport的MaxIdleConnsPerHost(建议设为 N 或略高)
单个请求必须设超时,且不能只靠 context.WithTimeout
context.WithTimeout 看似够用,但 HTTP 客户端真正发起连接、读响应体时,仍可能卡在底层 syscall 上。必须双保险。
- 显式设置
http.Client.Timeout(如30 * time.Second),它会覆盖 context 超时对底层连接的影响 - 同时用
context.WithTimeout包裹client.Do(),捕获context.DeadlineExceeded错误 - 如果用了自定义
http.Transport,记得设IdleConnTimeout和TLSHandshakeTimeout,否则空闲连接或 TLS 握手慢会拖垮整个池 - 错误日志里看到
net/http: request canceled (Client.Timeout exceeded while awaiting headers)?说明只设了 context 超时,没设Client.Timeout
响应体不关闭会导致 goroutine 泄漏和内存暴涨
Go 的 http.Response.Body 是惰性读取的,不手动 Close(),底层 TCP 连接就无法复用,连接池迅速枯竭,后续请求全卡在 dial tcp 阶段。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 每条
resp, err := client.Do(req)后,必须紧跟defer resp.Body.Close()(注意 defer 在循环里要包一层函数,否则只关最后一个) - 更安全写法:
if resp != nil && resp.Body != nil { defer resp.Body.Close() } - 如果只读状态码、Header,也得关;如果用
ioutil.ReadAll或io.Copy读完 body,关不关看似没差别——但关了才能复用连接 - 漏关的典型现象:
lsof -p <pid> | grep "TCP.*ESTABLISHED" | wc -l</pid>持续上涨,且netstat -an | grep TIME_WAIT大量堆积
错误处理别只判 err != nil,HTTP 状态码也要检查
client.Do() 返回 err == nil 只代表网络层成功,不代表业务成功。4xx/5xx 响应体照常返回,resp.StatusCode 才是关键。
- 务必检查
resp.StatusCode 或按需判断具体码(如只接受 200/201) - 不要在
err != nil分支里直接 return,否则 401、503 这类响应会被当成网络错误吞掉 - 读
resp.Body前先确认resp.StatusCode,避免对 404 响应体还调json.Unmarshal导致 panic - 示例片段:
if resp.StatusCode = 300 { return fmt.Errorf("HTTP %d: %s", resp.StatusCode, resp.Status) }
并发数不是越大越好,真实接口响应时间、目标服务承受力、本地文件描述符上限这三者要一起看。压测时盯住 netstat -s | grep -i "failed" 和 Go 的 runtime.NumGoroutine(),比单纯看 QPS 更早暴露问题。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!










