cpu密集型任务设runtime.numcpu()为安全起点,io密集型可设8–16但需压测验证;超32后调度开销反升,吞吐未必增加,避免按任务数线性放大worker数。

worker 数量设多少才不卡也不浪费
CPU 密集型任务(如图像缩放、加密计算)设 runtime.NumCPU() 是安全起点;IO 密集型(HTTP 请求、数据库查询)可设 8–16,但必须压测验证——超过 32 后调度开销反升,吞吐未必增加。
常见错误是按任务数线性放大 worker 数:1000 个请求配 1000 个 goroutine,结果内存暴涨、GC 频繁、调度器卡住。
实际中,numWorkers = 4 处理 10k HTTP 请求往往比 64 更稳,因为网络延迟天然让 worker 大部分时间在等待,不是真正在跑。
jobs channel 缓冲大小怎么选
缓冲大小本质是「允许积压的任务数」,不是越大越好。
设太小(如 make(chan Task, 1)):主协程发第 2 个任务就阻塞,吞吐上不去;
设太大(如 make(chan Task, 10000)):突发流量全塞进内存,OOM 风险高,且失去限流意义;
合理值取决于任务平均处理时长和峰值 QPS。例如平均耗时 200ms、峰值每秒 50 个任务,缓冲设 100 足够应对 2 秒突发。
别用 make(chan Task, 0)(无缓冲)——除非你确定每个 task 都能立刻被 worker 拿走,现实中几乎不可能。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
为什么 close(jobs) 必须在 wg.Wait() 之前
close(jobs) 是通知 worker “不再来新任务了”,但 worker 还得把已读到的最后一个任务做完再退出;wg.Wait() 是等所有 worker 真正结束。
如果先 wg.Wait() 再 close(jobs):worker 还在 for job := range jobs 里等着,永远收不到关闭信号,死锁;
如果任务发完就立刻 close(jobs),但没等 wg.Wait() 就去关 results:worker 可能还在往 results 写,触发 panic: send on closed channel;
正确顺序只有这一种:close(jobs) → wg.Wait() → close(results)(如果需要)。
recover() 不加 defer 就等于没加
worker 函数里写 defer func() { recover() }() 是防止单个任务 panic 导致整个 worker 退出——但必须包在 for job := range jobs 循环外层,否则 recover 只生效一次。
常见错误是把 recover 放在循环内部,或漏掉 defer,结果一个 panic 就让那个 worker 永久消失,剩余任务全堆积在 jobs 里;
更隐蔽的问题是 recover 后没 log,panic 黑箱发生,你只看到任务变慢或结果缺失,查不出原因;
别依赖 recover 掩盖设计问题:该校验的参数、该 timeout 的 context,不能全靠 recover 挡着。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










