Go语言中`WaitGroup`的介绍和使用示例

关于Go语言中WaitGroup
的介绍和使用示例,咱们用轻松易懂的方式分步拆解,并附上实用代码片段。以下内容结构清晰,适合新手到进阶开发者阅读👇
一、什么是WaitGroup?
WaitGroup
是Go语言sync
包提供的并发控制工具,核心作用是让主协程(goroutine)等待一组子协程全部完成任务后再继续执行。类似其他语言中的“线程栅栏”。
适用场景举例:
- 批量处理任务(如并发下载多个文件)
- 数据分片计算后汇总结果
- 确保所有协程就绪后再触发主逻辑
二、核心方法:3个关键操作
WaitGroup
仅包含3个方法,轻松上手:
-
Add(int)
设置需要等待的协程数量。例如,启动5个任务时调用wg.Add(5)
。 -
Done()
每个协程完成任务后调用,相当于计数器减1。通常用defer wg.Done()
确保执行。 -
Wait()
主协程调用此方法会阻塞,直到所有子协程完成(计数器归零)。
三、使用示例:分步骤指南
示例1:基础用法(模拟并发任务)
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var wg sync.WaitGroup
taskCount := 3
wg.Add(taskCount)
for i := 0; i < taskCount; i++ {
go func(id int) {
defer wg.Done() // 确保任务完成时调用
time.Sleep(time.Duration(id) * time.Second)
fmt.Printf("任务%d完成!\n", id)
}(i)
}
fmt.Println("主协程等待中...")
wg.Wait()
fmt.Println("所有任务完成!")
}
输出结果:
主协程等待中...
任务0完成!
任务1完成!
任务2完成!
所有任务完成!
解析:主协程通过wg.Wait()
等待,直到3个子协程均调用Done()
。
示例2:实战场景(并发检查就绪状态)
参考中的“赛跑”案例,模拟所有运动员就位后触发发令:
func main() {
var wait sync.WaitGroup
runnerCount := 5
wait.Add(runnerCount)
for i := 0; i < runnerCount; i++ {
go func(id int) {
defer wait.Done()
fmt.Printf("运动员%d已就位\n", id)
}(i)
}
fmt.Println("等待所有运动员准备...")
wait.Wait()
fmt.Println("发令枪响!比赛开始!")
}
四、注意事项(避坑指南)
-
计数器匹配:
Add(n)
的参数必须与后续Done()
调用次数一致,否则可能引发panic。- 建议在启动协程前调用
Add()
,避免并发操作导致计数错误。
-
避免重用问题:
一组WaitGroup
未完全结束前(如还在Wait()
中),不要复用同一实例。 -
延迟调用
Done()
:
使用defer wg.Done()
确保即使协程异常退出也能减少计数器。
五、总结
WaitGroup
是Go语言并发编程中的“协调员”,通过简洁的API实现多协程同步。使用时牢记计数器匹配原则,结合defer
确保健壮性,即可轻松驾驭并发任务场景~
