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)
这里的匿名函数如何退出呢?
您需要使用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 所有者有责任处理取消信号