
go 主函数退出后,程序立即终止,导致未执行完的 goroutine 被强制结束;需使用 sync.waitgroup 等同步机制等待所有 goroutine 完成。
go 主函数退出后,程序立即终止,导致未执行完的 goroutine 被强制结束;需使用 sync.waitgroup 等同步机制等待所有 goroutine 完成。
在 Go 中,goroutine 是轻量级并发执行单元,但其生命周期不绑定于主函数——这是初学者最常忽略的关键点。你提供的代码看似逻辑清晰:循环 20 次,每次启动一个 goroutine 打印 i + 100。然而运行后却没有任何输出,根本原因在于:main() 函数执行完即刻退出,整个程序进程终止,此时绝大多数(甚至全部)goroutine 还未来得及被调度执行。
这并非 bug,而是 Go 并发模型的明确设计:goroutine 不会阻塞主 goroutine(即 main),也不自动“等待”完成。要确保它们执行完毕,必须显式同步。
✅ 正确做法是使用 sync.WaitGroup:
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
for i := 0; i <p>⚠️ 注意事项:</p>
-
wg.Add(1)必须在go语句之前调用,否则存在竞态风险(如Add和Done顺序错乱); - 闭包参数
j int是关键:直接捕获循环变量i会导致所有 goroutine 打印相同值(如20 + 100 = 120),因为i在循环结束后已为20。此处通过传参j实现值拷贝,避免闭包陷阱; -
defer wg.Done()应放在 goroutine 内部最外层,确保无论函数如何返回(包括 panic),都能正确通知 WaitGroup。
? 替代方案(进阶):也可使用 channel 配合 range 或 select 实现同步,但 WaitGroup 是最直观、高效且语义明确的选择,适用于“等待一组任务完成”的典型场景。
总结:Go 的并发是“非抢占式协作”的,主 goroutine 不等待子 goroutine 是默认行为,而非异常。理解并主动管理生命周期,是写出健壮并发程序的第一步。










