wx

关注公众号

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


关于Go语言中WaitGroup的介绍和使用示例,咱们用轻松易懂的方式分步拆解,并附上实用代码片段。以下内容结构清晰,适合新手到进阶开发者阅读👇


一、什么是WaitGroup?
WaitGroup是Go语言sync包提供的并发控制工具,核心作用是让主协程(goroutine)等待一组子协程全部完成任务后再继续执行。类似其他语言中的“线程栅栏”。

适用场景举例:

  • 批量处理任务(如并发下载多个文件)
  • 数据分片计算后汇总结果
  • 确保所有协程就绪后再触发主逻辑

二、核心方法:3个关键操作
WaitGroup仅包含3个方法,轻松上手:

  1. Add(int)
    设置需要等待的协程数量。例如,启动5个任务时调用wg.Add(5)

  2. Done()
    每个协程完成任务后调用,相当于计数器减1。通常用defer wg.Done()确保执行。

  3. 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("发令枪响!比赛开始!")  
}  

四、注意事项(避坑指南)

  1. 计数器匹配:

    • Add(n)的参数必须与后续Done()调用次数一致,否则可能引发panic。
    • 建议在启动协程前调用Add(),避免并发操作导致计数错误。
  2. 避免重用问题:
    一组WaitGroup未完全结束前(如还在Wait()中),不要复用同一实例。

  3. 延迟调用Done()
    使用defer wg.Done()确保即使协程异常退出也能减少计数器。


五、总结
WaitGroup是Go语言并发编程中的“协调员”,通过简洁的API实现多协程同步。使用时牢记计数器匹配原则,结合defer确保健壮性,即可轻松驾驭并发任务场景~

wx

关注公众号

©2017-2023 鲁ICP备17023316号-1 Powered by Hugo