go - 如何尽早从循环内的 gouroutine 返回错误?
问题描述
我在一个循环中有一个 goroutine,我处理错误的方式是将它添加到一个通道中,并且在所有 goroutine 完成后,我检查是否有错误并相应地返回。
这样做的问题是我想在收到错误后立即返回错误,这样我就不会花时间等待所有 goroutine 完成,因为它效率低下。
我尝试添加select
语句,但它不起作用,我无法select
在 goroutines 中添加语句,因为我也想退出 for 循环和try
函数。
我怎样才能做到这一点?
这是代码:
package main
import (
"sync"
"runtime"
"fmt"
"errors"
)
func try() (bool, error) {
wg := new(sync.WaitGroup)
s := []int{0,1,2,3,4,5}
ec := make(chan error)
for i, val := range s {
/*
select {
case err, ok := <-ec:
if ok {
println("error 1", err.Error())
return false, err
}
default:
}
*/
wg.Add(1)
i := i
val := val
go func() {
err := func(i int, val int, wg *sync.WaitGroup) error {
defer wg.Done()
if i == 3 {
return errors.New("one error")
} else {
return nil
}
}(i, val, wg)
if err != nil {
ec <- err
return
}
}()
}
wg.Wait()
select {
case err, ok := <-ec:
if ok {
println("error 2", err.Error())
return false, err
}
default:
}
return true, nil
}
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
b, e := try()
if e != nil {
fmt.Println(e.Error(), b)
}
}
解决方案
在wg.Wait()
你的select
声明之前,你实际上是在等待所有的 goroutine 返回。
问题是我想在收到错误后立即返回
我假设你的意思是只要其中任何一个返回错误就停止运行 goroutine。
在这种情况下,您可以使用context.Context
来管理取消,但更好的是 an errgroup.Group
,它很好地结合了上下文功能和同步:
包 errgroup 为处理公共任务的子任务的 goroutine 组提供同步、错误传播和上下文取消。
特别是Group.Go
:
第一次调用返回非 nil 错误会取消该组;Wait 会返回它的错误。
import (
"sync"
"runtime"
"fmt"
"errors"
"golang.org/x/sync/errgroup"
)
func try() (bool, error) {
errg := new(errgroup.Group)
s := []int{0,1,2,3,4,5}
for i, val := range s {
i := i
val := val
errg.Go(func() error {
return func(i int, val int) error {
if i == 3 {
return errors.New("one error")
} else {
return nil
}
}(i, val)
})
}
if err := errg.Wait(); err != nil {
// handle error
}
return true, nil
}
推荐阅读
- python - 如何在 Google Cloud Platform 中的 Google AI Platform 中安装 Spark 依赖项
- python - 有什么神奇的命令可以不在 Python 中运行特定的单元格吗?
- java - 如何按字段对对象列表进行排序?
- angular - Angular - 如何使用 sum 和 group by
- linux - AWS CloudWatch 日志组命名约定
- apache-spark - Spark:日文字母在 HDFS 中创建的 Paquet 文件中出现乱码
- python - 强制 pandas.to_excel 将数据写入“文本”而不是“常规”格式
- office-js - 如何在加载项命令中使用 imageMSO 图标
- performance - LoadRuner CPU 在启用 TLS 的情况下非常高
- angularjs - AngularJs 验证,所有输入必须有不同的值