

新闻资讯
技术学院Go并发下载需用goroutine处理任务、channel协调状态,并通过带缓冲channel(如sem := make(chan struct{}, 5))实现并发控制,配合WaitGroup确保worker启动完成后再关闭输入channel。
在 Go 中实现并发文件下载,核心是用 goroutine 处理多个下载任务,用 channel 协调状态、传递结果或控制并发数。不加限制地启动成百上千个 goroutine 可能压垮网络或目标服务器,所以需结合 semaphore(信号量)或带缓冲的 channel 实现并发控制。
任务把待下载的 URL 列表发到一个输入 channel,启动固定数量的工作 goroutine 从该 channel 消费 URL 并执行下载。每个 goroutine 下载完成后,将结果(如文件名、错误)发到输出 channel。主 goroutine 从输出 channel 收集结果,统一处理成功或失败情况。
chan string(URL)或自定义结构体(含 URL、保存路径等)chan DownloadResult,其中 DownloadResult 包含 URL、Filename、Err error
sync.WaitGroup 确保所有 worker 启动完成后再关闭输入 channel最轻量的方式是创建一个容量为 N 的 channel(比如 sem := make(chan struct{}, 5)),每个 goroutine 在开始下载前先向它发送一个占位符(sem ),下载结束后再取出()。这样最多只有 5 个 goroutine 同时运行。
都有对应 sem ,且 recover 或 defer 中也要释放
acquire(sem) 和 release(sem)
HTTP 下载必须设超时,否则单个卡住会拖慢整个流程。推荐用 http.Client 配合 context.WithTimeout;失败时可简单重试 1–2 次,避免因临时网络抖动导致整体失败。
os.MkdirAll
io.Copy 流式写入,避免把整个响应体读进内存启动 5 个 worker,从 urls 切片生成输入 channel,收集结果并打印统计:
sem := make(chan struct{}, 5)
results := make(chan DownloadResult, len(urls))
for _, url := range urls {
go func(u string) {
sem <- struct{}{}
defer func() { <-sem }()
filename, err := downloadFile(u)
results <- DownloadResult{URL: u, Filename: filename, Err: err}
}(url)}
// 启动收集 goroutine 或在主协程中 range results
for i := 0; i ail %s: %v", res.URL, res.Err)
} else {
log.Printf("done %s → %s", res.URL, res.Filename)
}
}