跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

Go语言如何同步协程_Go语言WaitGroup同步教程【必看】

sync.WaitGroup 是轻量不可复制的同步原语,Add 必须在 goroutine 启动前调用,Done 应 defer 调用,可重用但禁止 Add 与 Wait 并发,零值安全但严禁复制。
sync.WaitGroup
不是“教程工具”,它是一个轻量、不可复制、需谨慎调用的同步原语——用错一次就 panic,写对了才真正省事。 WaitGroup.Add 必须在 goroutine 启动前调用 这是最常踩的坑:把
wg.Add(1)
放在
go
语句之后,或塞进 goroutine 里,会导致
Wait()
永远不返回,或 panic “negative WaitGroup counter”。
Add
的作用是预登记“待等待任务数”,必须在
go
启动前完成 闭包中若用循环变量(如
for i := range urls
),要传参避免所有 goroutine 共享同一个
i
值 如果任务数动态不确定(比如从 channel 拉取),得先 collect 再
Add(len(tasks))
,不能边拉边
Add
Done 要确保执行,推荐 defer wg.Done()
Done()
是计数器减 1,漏调 = 计数器卡住 =
Wait()
死锁。用
defer
是最稳妥的方式,但要注意: 必须在 goroutine 内部调用,不能由主 goroutine 代劳 如果函数有多个 return 路径(比如 error early return),
defer
能覆盖全部出口 不要在
Done()
后再操作共享资源(如往结果 channel 写入),除非你已加锁或用其他同步机制保护 WaitGroup 可重用,但不能并发 Add + Wait 混用 很多人以为
WaitGroup{}
是一次性对象,其实只要
Wait()
返回后计数器为 0,它就回到了零值状态,可以再次
Add()
。 go语言参考手册 中文CHM版 Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译 下载 重用没问题:
wg.Wait()
返回后,直接
wg.Add(5)
启新一批任务是安全的 但禁止在
Wait()
还没返回时,从另一个 goroutine 调用
Add()
—— 这会触发 panic “WaitGroup misuse” 多个 goroutine 同时调用
Wait()
是允许的,计数器归零时它们会一起被唤醒 别把 WaitGroup 当 channel 用,错误处理要另配机制
WaitGroup
只回答“是否全做完”,不回答“做得对不对”。常见错误是只等不收错: 立即学习 “ go语言免费学习笔记(深入) ”; 想收集错误?得配
chan error
或切片 + 互斥锁,
WaitGroup
本身不传值 想收返回结果?同样要额外 channel 或指针参数,
WaitGroup
不持有任何业务数据 别试图用
WaitGroup
控制超时——它没有 context 支持,超时得靠
select
+
time.After
或
context.WithTimeout
真正容易被忽略的点是:WaitGroup 的零值是安全的,但它的内存布局含原子字段,一旦被复制(比如作为 struct 字段值拷贝、传参没取地址),就会破坏内部状态。所以永远用
*sync.WaitGroup
传参,声明时用
var wg sync.WaitGroup
,传给函数时传
&wg
。

相关文章