sync.WaitGroup 是 Go 语言标准库 sync 包中的一个并发原语,用于等待一组 Goroutine 完成执行。它通过计数器机制实现协程的同步,常用于主 Goroutine 阻塞等待所有子 Goroutine 完成任务后再继续执行。
核心方法
Add(delta int)- 增加或减少 WaitGroup 的计数器值(通常为正数)。
 - 在启动新 Goroutine 前调用,表示需要等待的任务数。
 delta可以是负数(但需确保计数器不为负)。
Done()- 将计数器减 1(等价于 
Add(-1))。 - 在 Goroutine 内部 defer 调用,确保任务完成后通知 WaitGroup。
 
- 将计数器减 1(等价于 
 Wait()- 阻塞当前 Goroutine,直到计数器归零。
 - 通常由主 Goroutine 调用。
 
使用示例
package main
import (
	"fmt"
	"sync"
	"time"
)
func worker(id int, wg *sync.WaitGroup) {
	defer wg.Done() // 确保任务完成后计数器减1
	fmt.Printf("Worker %d starting\n", id)
	time.Sleep(time.Second) // 模拟耗时任务
	fmt.Printf("Worker %d done\n", id)
}
func main() {
	var wg sync.WaitGroup
	for i := 1; i <= 3; i++ {
		wg.Add(1) // 每个任务开始前增加计数器
		go worker(i, &wg)
	}
	wg.Wait() // 阻塞直到所有任务完成
	fmt.Println("All workers completed")
}
关键注意事项
指针传递
WaitGroup 必须通过指针传递给 Goroutine,否则会导致副本操作,引发死锁。计数器的正确性
Add()必须在Wait()之前调用(通常在启动 Goroutine 前)。Done()次数必须与Add()的总增量匹配,否则会 panic。
避免竞态条件
不要在多个 Goroutine中并发调用Add()(建议在主 Goroutine中集中管理)。不可重用
一个 WaitGroup在计数器归零后不能重复使用(除非重新初始化)。
典型应用场景
- 批量异步任务等待:如并发处理一批文件下载、数据库查询等。
 - 服务优雅退出:等待所有后台 Goroutine清理资源后再关闭程序。
 - 测试多线程逻辑:确保所有测试用例的并发操作完成后再校验结果。
 
如果涉及更复杂的同步需求(如错误传递),可结合 channel或 errgroup.Group(扩展库)使用。
内容由零声教学AI助手提供,问题来源于学员提问


        
        
        
        
        
        
        
        
        
                
                
                
                
                
                
                