WaitGroup如何其中一个协程发生错误,应该如何处理
等待一个协程组全部正确完成则结束;但其中一个协程发生错误,这时候就会阻塞,全部停止运行(本次任务失败)以免浪费系统资源,此时可以结合通道(channel)或者 select 语句两种方式来处理。
1、考虑使用两个通道:一个用于报告错误,另一个用于通知所有协程停止。在协程内部捕获错误,并将错误信息发送到错误通道。另一个协程监听错误通道,一旦有错误发生,就会向停止通知通道发送信号,通知所有协程停止运行。
package main
import (
"fmt"
"sync"
)
func worker(id int, errCh chan error, wg *sync.WaitGroup) {
defer wg.Done()
// 模拟错误
if id == 2 {
errCh <- fmt.Errorf("error occurred in worker %d", id)
return
}
// 做一些工作
fmt.Printf("Worker %d is working...\n", id)
}
func main() {
var wg sync.WaitGroup
errCh := make(chan error)
stopCh := make(chan struct{})
for i := 0; i < 5; i++ {
wg.Add(1)
go worker(i, errCh, &wg)
}
go func() {
err := <-errCh
if err != nil {
fmt.Println("Error occurred:", err)
close(stopCh)
}
}()
go func() {
wg.Wait()
close(errCh)
}()
// 等待通知,停止所有协程
<-stopCh
fmt.Println("All workers stopped.")
}
errCh 通道用于发送错误信息,stopCh 通道用于通知所有协程停止。如果有一个协程发生错误,就会关闭 stopCh 通道,通知其他协程停止运行。
2、select 语句是 Go 中用于多路非阻塞的关键字,可以用于监听多个通道的操作。可以在 select 语句中组合使用 WaitGroup 和通道来实现对协程组的控制。
package main
import (
"fmt"
"sync"
)
func worker(id int, errCh chan error, wg *sync.WaitGroup) {
defer wg.Done()
// 模拟错误
if id == 2 {
errCh <- fmt.Errorf("error occurred in worker %d", id)
return
}
// 做一些工作
fmt.Printf("Worker %d is working...\n", id)
}
func main() {
var wg sync.WaitGroup
errCh := make(chan error)
for i := 0; i < 5; i++ {
wg.Add(1)
go worker(i, errCh, &wg)
}
go func() {
wg.Wait()
close(errCh)
}()
for {
select {
case err, ok := <-errCh:
if ok {
fmt.Println("Error occurred:", err)
// 处理错误,根据需要执行相关操作
} else {
fmt.Println("All workers completed successfully.")
return
}
}
}
}
select 语句监听 errCh 通道,等待错误消息。当收到错误消息时,可以根据需要执行相应的错误处理。当 errCh 通道关闭时,ok 的值为 false,表示所有协程已经成功完成。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」