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

How to exit when the first error occurs for one of the goroutines within a wait Group?

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
}

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

您需要使用ErrGroup

这就是ErrGroup.Go所做的

The first call to return a non-nil error cancels the group; its error will be returned by Wait.

所以当任何一个goroutinereturn出错时,其他goroutines会自动取消。

用法:

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
}

编辑:
也许答案不够详细。当文档说其他 goroutines 将被取消时,这意味着被 errGroup 编辑的 context 将被取消。所以每个 go routine owner 都必须在他们的代码中处理这个取消。
示例: https://go.dev/play/p/hXWjtN4uj06

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