WaitGroup用于等待一组goroutine完成,通过Add、Done、Wait方法实现同步。典型用法是在主协程中Add增加计数,每个子协程完成后调用Done,最后主协程Wait阻塞直至所有任务结束。常见于并发请求或批量处理场景,需注意Add在goroutine外调用、避免复制WaitGroup、配合defer确保Done执行。可与Context结合实现超时控制,是Go并发编程中可靠且高效的同步工具。

在Go语言中,WaitGroup 是
sync
包提供的同步原语,用于等待一组并发的goroutine执行完成。它特别适合主协程需要等待多个子任务结束后再继续的场景。使用 WaitGroup 可以避免程序提前退出或资源未释放的问题。
WaitGroup 基本用法
WaitGroup 提供三个核心方法:
Add(n):增加计数器,表示要等待的goroutine数量。 Done():在goroutine中调用,表示当前任务完成,计数器减1。 Wait():阻塞主协程,直到计数器归零。
典型结构如下:
var wg sync.WaitGroupfor i := 0; i < 5; i++ { wg.Add(1) go func(id int) { defer wg.Done() // 执行任务 fmt.Printf("任务 %d 完成n", id) }(i)}wg.Wait() // 等待所有任务完成fmt.Println("所有子任务已完成")
常见使用模式
实际开发中,常结合 for 循环启动多个goroutine,并确保每个都正确调用 Done()。推荐使用 defer wg.Done() 防止因 panic 或提前返回导致计数器不一致。
立即学习“go语言免费学习笔记(深入)”;
示例:并发抓取多个URL
package mainimport ( "fmt" "net/http" "sync")func fetch(url string, wg *sync.WaitGroup) { defer wg.Done() resp, err := http.Get(url) if err != nil { fmt.Printf("请求失败 %s: %vn", url, err) return } defer resp.Body.Close() fmt.Printf("成功获取 %s,状态码: %dn", url, resp.StatusCode)}func main() { urls := []string{ "https://httpbin.org/get", "https://httpbin.org/delay/2", "https://httpbin.org/status/200", } var wg sync.WaitGroup for _, url := range urls { wg.Add(1) go fetch(url, &wg) } wg.Wait() fmt.Println("所有HTTP请求完成")}
注意事项
不要复制WaitGroup:传递时应使用指针,否则会引发竞态或panic。 Add的调用应在goroutine外:如果在goroutine内部Add,可能主协程还没注册完就进入Wait,导致漏等。 计数不能为负:Done调用次数不能超过Add设定值,否则panic。
错误示例(避免):
go func() { wg.Add(1) // 错误:Add在goroutine内 defer wg.Done()}()
与Context结合使用
在更复杂的场景中,可将 WaitGroup 与 context.Context 结合,实现超时控制或取消机制。WaitGroup负责等待完成,Context负责中断信号。
例如,设置整体超时:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)defer cancel()// 启动任务...wg.Wait() // 仍需等待,但受上下文约束
基本上就这些。WaitGroup简单高效,是Go中控制并发任务生命周期的常用工具。只要注意Add时机和资源安全,就能可靠使用。
以上就是Golang使用WaitGroup控制子任务完成的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1405002.html
微信扫一扫
支付宝扫一扫