在 Go 语言中,主协程要通过什么方式才能确保在其余协程全部执行完毕之后再继续后续操作?
考察说明
考查 Go 语言中并发同步的基本机制和常见工具的使用。
回答思路
- 【回答框架 1】Go 语言中,主协程等待其他协程完成的主要方式包括使用 sync.WaitGroup、通道(channel)以及 context 包。其中 sync.WaitGroup 是最直接和常用的方式。
- 【回答框架 2】sync.WaitGroup 通过三个方法实现等待:Add(delta) 设置需要等待的协程数量,Done() 在每个协程完成时调用(通常通过 defer 确保调用),Wait() 阻塞主协程直到计数归零。使用时需注意 Add 的调用时机,必须在启动协程前调用,且计数不能为负。
- 【回答框架 3】通道方式中,可以创建一个无缓冲或带缓冲的通道,每个协程完成时发送一个信号,主协程接收相应数量的信号后继续。这种方法更适合传递结果或需要控制并发数量的场景。
- 【回答框架 4】context 包主要用于取消和超时控制,但也可以结合 Done() 通道实现等待,不过更常用于管理协程的生命周期而不是简单的等待。
- 【回答框架 5】如果使用 errgroup 包(golang.org/x/sync/errgroup),可以同时实现等待和错误传播,适合需要收集错误并提前取消的场景,但这是第三方扩展包。
- 【关键点 1】sync.WaitGroup 是主协程等待其他协程完成的标准方法,核心是 Add、Done、Wait 三个方法。
- 【关键点 2】使用 WaitGroup 时,Add 必须在启动协程前调用,Done 通常通过 defer 保证执行。
- 【关键点 3】通道方式通过发送和接收信号实现同步,适合传递结果或控制并发数量。
- 【关键点 4】context 包主要用于取消和超时,而非专门的等待机制。
- 【关键点 5】errgroup 可同时处理等待和错误传播,但需要引入额外依赖。
- 【易错点 1】WaitGroup 的计数器不能为负,否则会 panic,因此 Add 和 Done 必须配对正确。
- 【易错点 2】WaitGroup 不能在协程内部调用 Add,否则可能导致主协程提前退出或计数错误。
- 【易错点 3】使用通道时,如果缓冲区大小设置不当或信号数量不匹配,可能导致死锁或主协程一直阻塞。