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

sof*_*fs1 7 channel worker go goroutine

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
}
Run Code Online (Sandbox Code Playgroud)

这里的匿名函数如何退出呢?

Ban*_*ore 3

您需要使用ErrGroup

这就是 ErrGroup.Go 的作用

第一次调用返回非零错误会取消该组;其错误将由 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
}
Run Code Online (Sandbox Code Playgroud)

编辑:
也许答案描述性不够。当文档说其他 goroutine 将被取消时,这意味着context返回的 goroutineerrGroup将被取消。因此,每个 go 例程所有者都必须在其代码中处理此取消。
示例: https: //go.dev/play/p/hXWjtN4uj06

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

  • g.Wait() 返回,直到所有 go 例程返回。 (3认同)