
本文介绍使用 go 的 channel 和 goroutine 池控制 http 并发请求数量的核心方法,通过固定工作协程池(如 10 个)逐批处理 url 列表,避免一次性发起全部 200 个请求,确保资源可控、逻辑清晰。
本文介绍使用 go 的 channel 和 goroutine 池控制 http 并发请求数量的核心方法,通过固定工作协程池(如 10 个)逐批处理 url 列表,避免一次性发起全部 200 个请求,确保资源可控、逻辑清晰。
在 Go 中实现「最多 N 个并发 HTTP 请求」的常见误区是:为每个 URL 启动一个 goroutine(如 go httpRequest(url)),导致瞬间创建大量连接,既浪费资源又易触发限流或超时。正确做法是构建一个固定大小的工作协程池(Worker Pool),配合带缓冲或无缓冲 channel 实现任务分发与同步。
以下是一个完整、可运行的示例,支持从文件读取 200 个 URL,并始终仅并发执行最多 10 个 HTTP GET 请求:
package main
import (
"bufio"
"fmt"
"io"
"net/http"
"os"
"time"
)
// Worker 执行单个 HTTP 请求并发送结果到 results channel
func worker(id int, jobs <p>? <strong>关键设计说明:</strong> </p>
-
jobs是一个带缓冲的 channel(容量为maxWorkers),但更推荐使用无缓冲 channel(make(chan string))以实现严格“一进一出”阻塞语义;本例用缓冲仅作示例,实际中close(jobs)+ range 更安全。 - 所有 worker 在
for url := range jobs中持续监听,一旦 job 被消费即立即处理下一个,天然形成“10 个活跃并发”。 - 主 goroutine 通过
jobs 发送任务,当所有 10 个 worker 都忙碌时,该操作会<strong>自动阻塞</strong>,直到任一 worker 完成并读走一个 job —— 这正是实现“最大并发数”的核心机制。 - 使用
close(jobs)配合range可优雅终止 worker,避免 goroutine 泄漏。
⚠️ 注意事项:
- 务必调用
resp.Body.Close()防止连接复用泄漏; - 生产环境应添加重试、熔断、日志、指标监控;
- 若需按顺序返回结果,可在发送 job 时附带索引,或使用
sync.Map/切片 + mutex 记录; -
http.Client应复用(而非每次新建),并配置合理的Transport.MaxIdleConnsPerHost(默认 2,建议设为maxWorkers或更高)。
通过该模式,你不仅能精准控制并发度,还能轻松扩展至任意规模(如 50 并发、100 并发),且代码结构清晰、易于测试与维护。










