为了账号安全,请及时绑定邮箱和手机立即绑定

当等待组中的一个 goroutine 发生第一个错误时如何退出?

当等待组中的一个 goroutine 发生第一个错误时如何退出?

Go
慕侠2389804 2022-06-01 15:50:30
func getRecords(ctx context.Context, ids *[]Id) error {    ctx, cancel := context.WithTimeout(ctx, DefaultTimeout)    defer cancel()    var wg sync.WaitGroup    size := len(*ids)    allErrors := make(chan error, size)    for i := 0; i < size; i++ {        wg.Add(1)        go func(x int){            err := //call to other func which return error type. nil or error            if err != nil { // I will be creating n goroutines. How to exit rightaway if one of                             // them return error                allErrors <- err             }            wg.Done()        }(i)    }    go func() {        wg.Wait()        close(allErrors)    }    return nil}如何在这里退出匿名函数?
查看完整描述

1 回答

?
沧海一幻觉

TA贡献1824条经验 获得超5个赞

您需要使用ErrGroup


这就是 ErrGroup.Go 所做的


第一次调用返回非 nil 错误会取消该组;Wait 会返回它的错误。


因此,当任何一个 goroutine 返回错误时,其他 goroutine 将自动取消。


用法:


errs, ctx = errgroup.WithContext(ctx)


for i := 0; i < size; i++ {

    errs.Go( func() error{

        ...

    })

}


if err := g.Wait(); err != nil {

    // Handle Errors from GoRoutines

}

编辑:

也许答案描述性不够。当文档说其他 goroutine 将被取消时,这意味着context返回的goroutine 将被errGroup取消。所以每个 goroutine 所有者必须在他们的代码中处理这个取消。

示例: https ://go.dev/play/p/hXWjtN4uj06


真实示例:当您的 golang 服务启动时,您可能在一个例程中启动 HTTP 服务器,在另一个例程中启动 Kafka 消费者,最后一个例程中启动 grpc 服务器。现在,如果其中任何一个停止,您想要停止整个服务(考虑服务已关闭)。然后你与所有这些 goroutine 共享 errGroupd 上下文(幸运的是,这些底层服务已经处理了这个上下文取消逻辑,所以你不必编写一个)但是如果那个 goroutine 做了一些自定义的事情,那么它的 goroutine 所有者有责任处理取消信号


查看完整回答
反对 回复 2022-06-01
  • 1 回答
  • 0 关注
  • 113 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信