Go并发下载文件需先HEAD确认服务器支持Range请求,再按Content-Length合理分块(如4块/100MB),各goroutine用独立Range请求写入文件指定偏移,最后校验总大小与哈希值。
用 Go 语言实现并发下载文件,核心是把一个大文件按字节范围分块,再用多个 goroutine 并发请求各块,最后合并。关键不是“开很多协程”,而是合理分块、处理 HTTP Range 请求、避免竞争和资源耗尽。
不是所有服务器都允许分块下载。先发一个 HEAD 请求,检查响应头是否包含 Accept-Ranges: bytes 或 Content-Range 字段:
http.Head(url) 获取响应头resp.Header.Get("Accept-Ranges") == "bytes",说明支持用 HEAD 请求拿到 Content-Length,再按需切分。例如 100MB 文件,开 4 个 goroutine,每块约 25MB:
start 和 end(注意 end 是闭区间,HTTP Range 是 inclusive)
3. 并发发起 Range 请求并写入临时文件每个 goroutine 独立发起 GET 请求,设置 Range: bytes=start-end 头,并将响应 Body 写入文件指定偏移位置:
os.OpenFile(..., os.O_CREATE|os.O_RDWR) 打开文件,**不要用 O_TRUNC***os.File 或共享 file + file.WriteAt()(线程安全)http.Client{Timeout: 30 * time.Second}
所有块写完后,无需“合并”操作——因为已按偏移写入同一文件。只需做两件事:
Content-Length,不等说明某块写漏或截断ETag 或单独提供的 checksum注意:别用 ioutil.ReadAll + 内存拼接,大文件会 OOM;别用 channel 收集所有数据再写盘,失去流式优势;别在 goroutine 里用同一个 http.Client 不加限制,应复用 Transport 并设 MaxIdleConns。