errgroup
是 Go 语言标准库中的一个实用工具,它能够协调多个 goroutine 的并发执行,并监控它们的执行状态。下面是 errgroup
的基本用法:
- 导入
golang.org/x/sync/errgroup
包。
import (
"context"
"errors"
"fmt"
"golang.org/x/sync/errgroup"
)
- 创建一个
errgroup.Group
对象,并使用ctx, cancel
函数创建一个上下文对象。
func main() {
g, ctx := errgroup.WithContext(context.Background())
// ...
}
- 向
errgroup.Group
中添加一组要执行的 goroutine,每个 goroutine 都是一个函数,该函数必须返回一个 error 类型的值。
g.Go(func() error {
// do something
return nil
})
- 在任何一个 goroutine 返回非空的 error 错误时,所有 goroutine 都会被取消执行,并将这个错误作为结果返回。
g.Go(func() error {
// do something
return errors.New("error happened")
})
if err := g.Wait(); err != nil {
fmt.Println("Error happened: ", err)
}
完整的示例代码如下:
package main
import (
"context"
"errors"
"fmt"
"golang.org/x/sync/errgroup"
)
func main() {
g, ctx := errgroup.WithContext(context.Background())
g.Go(func() error {
fmt.Println("Start executing task1")
return nil
})
g.Go(func() error {
fmt.Println("Start executing task2")
return errors.New("error happened in task2")
})
g.Go(func() error {
select {
case <-ctx.Done():
fmt.Println("task3 canceled")
return ctx.Err()
default:
fmt.Println("Start executing task3")
return nil
}
})
if err := g.Wait(); err != nil {
fmt.Println("Error happened: ", err)
}
}
执行该程序,输出内容如下:
Start executing task1
Start executing task2
Start executing task3
task3 canceled
Error happened: error happened in task2
可以看到,在 goroutine 2 中返回了一个错误,导致所有的 goroutine 都被取消执行,并将此错误作为结果返回。同时还支持在某些 goroutine 中判断 context 是否被取消,并及时退出。