Go程序中goroutine不执行主因是main提前退出,需用sync.WaitGroup显式等待;CPU密集型任务并行慢可能因GOMAXPROCS=1或GC干扰;channel死锁常见于无缓冲chan发送无接收,应合理使用缓冲或worker pool限流。

goroutine 启动后不执行?检查是否主 goroutine 提前退出
Go 程序中启动 go func() 后没看到输出或结果,大概率是 main 函数返回、进程直接退出了。Go 不会自动等待子 goroutine 完成。
- 用
sync.WaitGroup显式等待:在启动前wg.Add(1),函数末尾wg.Done(),主 goroutine 调用wg.Wait() - 避免用
time.Sleep模拟等待——不可靠,容易误判完成时机 - 若任务有返回值,别把结果塞进全局变量再读取;优先用 channel 接收,或封装为带
return的闭包 +WaitGroup
多个 CPU 密集型任务并行跑不快?确认 GOMAXPROCS 设置与 runtime.GC 干扰
Go 默认将 GOMAXPROCS 设为系统逻辑 CPU 数,但若手动设为 1,所有 goroutine 就只能在一个 OS 线程上调度,无法真正并行执行计算任务。
- 启动时检查:
fmt.Println(runtime.GOMAXPROCS(0))—— 返回当前值;如为 1,加runtime.GOMAXPROCS(runtime.NumCPU()) - CPU 密集型任务中频繁触发 GC(比如分配大量中间切片)会显著拖慢吞吐;考虑复用
[]byte或使用sync.Pool - 避免在循环内无节制启动 goroutine(如百万级),应配合 worker pool 限流,否则调度器压力大、内存暴涨
用 channel 做并发结果收集,为什么出现 deadlock?
典型死锁场景:所有 goroutine 都在向一个未缓冲的 channel 发送,但没有 goroutine 在接收;或接收方在发送方全部启动前就退出了。
- 发送端必须配对
close(ch)(仅由 sender 关闭),接收端用for v := range ch安全遍历 - 缓冲 channel 可缓解阻塞,但缓冲区大小 ≠ 并发数;设太小仍会阻塞,设太大浪费内存;建议按任务批次大小预估(如
ch := make(chan int, 100)) - 别在同一个 goroutine 里既发又收无缓冲 channel —— 必死锁
需要精确控制并发数?用 worker pool 模式而非无限制 go func
直接对每个任务起 goroutine,在数据量大时极易 OOM 或被系统 kill;worker pool 把并发数压到可控范围,同时保持高吞吐。
立即学习“go语言免费学习笔记(深入)”;
- 核心结构:一个输入 channel(任务)、N 个常驻 goroutine(worker)、一个输出 channel(结果)
- 启动 N 个 worker:
for i := 0; i - 任务分发完后
close(tasks),worker 内用for task := range tasks自动退出;主 goroutine 用for i := 0; i 收集 - 注意:如果任务本身含阻塞 I/O(如 HTTP 请求),worker 数可略大于 CPU 核数;纯计算任务建议 ≤
runtime.NumCPU()










