Go并发API调用需用channel限流、context控制超时、WaitGroup+channel聚合结果、分层重试降级,并复用HTTP client连接。

用 Go 实现并发 API 调用,核心是合理利用 goroutine 和 channel 控制并发度,避免资源耗尽或服务被压垮。关键不在于“开越多越快”,而在于平衡吞吐、稳定与错误处理。
控制并发数量:用带缓冲的 channel 限流
无限制启动 goroutine 容易打爆本地文件描述符或远端服务。推荐用 channel 做信号量,限制同时运行的请求数:
- 初始化一个容量为 N 的 channel(如
sem := make(chan struct{}, 10)),每发起一个请求前先写入一个空结构体,执行完再读出 - 这样最多只有 10 个请求并行,其余协程会阻塞等待,天然实现平滑限流
- 比 time.Sleep 或全局计数器更安全,不会因 panic 导致计数失衡
统一管理请求生命周期:用 context 控制超时与取消
每个 HTTP 请求都应绑定 context,防止单个慢接口拖垮整批调用:
- 用
context.WithTimeout(ctx, 5*time.Second)包裹请求上下文,超时自动中断连接和读取 - 批量调用时可共用一个父 context,外部主动调用
cancel()即可中止所有未完成请求 - 注意:http.Client 默认不继承 context 超时,需显式传入
req.WithContext(...)或直接用http.NewRequestWithContext
聚合结果与错误:用 sync.WaitGroup + channel 收集响应
避免用锁同步 map 存结果,推荐“发射-收集”模式:
立即学习“go语言免费学习笔记(深入)”;
- 启动 goroutine 发起请求,完成后将结果(含 error)发送到同一 result channel
- 主 goroutine 启动 WaitGroup 计数,并在所有请求启动后关闭 result channel
- range 遍历 result channel,自然按完成顺序接收响应,也可配合 select 处理超时或提前退出
- 示例场景:调用 100 个用户信息接口,只需等最快 50 个返回即可继续后续逻辑,其余可忽略
重试与降级:简单但有效的健壮性设计
网络请求失败常见,但盲目重试会加剧问题。建议分层处理:
- 对 429(限流)、503(服务不可用)等状态码做指数退避重试(如 100ms → 200ms → 400ms),最多 2 次
- 对 400、401 等客户端错误直接失败,不重试
- 配置 fallback 值(如缓存数据、默认值),当重试后仍失败时兜底返回,保障主流程不中断
- 记录失败指标(如 Prometheus counter),便于监控异常突增
不复杂但容易忽略:HTTP client 复用 Transport、设置 MaxIdleConnsPerHost,否则高并发下会创建大量 TCP 连接,触发 “too many open files”。










