main函数提前退出会导致goroutine被强制终止;应使用sync.WaitGroup等待,避免time.Sleep;需配置http.Transport的MaxIdleConnsPerHost并加并发控制。

goroutine 启动后不执行?检查是不是 main 函数提前退出了
Go 程序里启动一堆 go downloadFile(...),结果什么都没下载——大概率是 main 函数跑完直接退出,所有 goroutine 被强制终止。Go 不会等 goroutine 自己结束。
- 最简解法:用
sync.WaitGroup记录正在运行的 goroutine 数量,在main末尾调用wg.Wait() - 别用
time.Sleep(5 * time.Second)临时凑数,它不可靠:下载快了会早退,慢了又卡住 - 如果下载逻辑里有错误(比如 URL 404),
go启动的函数内部 panic 也不会报到 main,得自己加recover或日志
并发太多导致 connection refused 或 timeout
一次性开 100 个 goroutine 去请求同一台服务器,大概率触发连接限制或被限流。HTTP 客户端底层复用 TCP 连接,但默认 http.DefaultTransport 的 MaxIdleConnsPerHost 是 2,根本撑不住高并发。
- 显式配置 Transport:
tr := &http.Transport{MaxIdleConnsPerHost: 50},再传给http.Client{Transport: tr} - 更稳妥的做法是加并发控制:用带缓冲的 channel 当“令牌桶”,比如
sem := make(chan struct{}, 10),每个 goroutine 先sem 再下载,结束后 <code><-sem - 注意 DNS 解析也可能成为瓶颈,尤其在容器环境;可考虑预热或用
net.Resolver控制超时
文件写入乱序或覆盖?别让多个 goroutine 直接写同一个 *os.File
如果所有 goroutine 都往同一个打开的 *os.File 写数据(比如拼接下载内容),结果就是字节交错、内容错乱。Go 的 Write 不是原子操作,也不是线程安全的。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 每个 goroutine 应该独立打开自己的目标文件,用唯一文件名(比如从 URL 提取 path 或加序号)
- 如果必须合并写入,让一个 goroutine 专门负责接收下载好的
[]byte并顺序写盘,其他只管下载和发送 —— 用chan []byte+range实现 - 别用
os.Stdout或log.Printf在多个 goroutine 里狂打日志,输出也可能混在一起;加锁或改用结构化日志库
URL 中带中文或特殊字符,http.Get 直接 panic
常见错误:http.Get("https://example.com/路径?name=张三") 报 parse https://example.com/路径?name=张三: invalid URL escape "%E5%" —— 这是因为 Go 的 url.Parse 要求输入已是合法编码格式。
立即学习“go语言免费学习笔记(深入)”;
- 必须先用
url.PathEscape和url.QueryEscape分别处理 path 段和 query 参数 - 推荐组合写法:
u := &url.URL{Scheme: "https", Host: "example.com", Path: "/路径"},再用u.RawQuery = url.Values{"name": {"张三"}}.Encode() - 别依赖用户输入的原始字符串拼 URL;哪怕只是
"?"或"#"没转义,也会解析失败
真正麻烦的不是启动 goroutine,而是让它们协作时不踩彼此的脚、不耗尽系统资源、不把错误吞进黑洞。越早把 WaitGroup、semaphore、url.Escape 当成默认配件用,后面 debug 越少翻车。

















