waitgroup如何其中一个协程发生错误,应该如何处理

发布时间 2023-12-07 14:25:29作者: 李若盛开

等待一个协程组全部正确完成则结束;但其中一个协程发生错误,这时候就会阻塞,全部停止运行(本次任务失败)以免浪费系统资源,此时可以结合通道(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,表示所有协程已经成功完成。