errgroup
是 Go 编程语言中的一个并发模式库,属于 golang.org/x/sync
包的一部分。它被广泛用于管理一组 goroutine 的并发执行,并简化错误处理。
errgroup
的主要作用包括:
- 并发管理:
errgroup
可以同时启动多个 goroutine,并等待所有 goroutine 执行完成。这样可以方便地管理并发任务。 - 错误处理: 在使用
errgroup
时,如果其中任何一个 goroutine 返回错误,errgroup
会捕获这个错误并返回,从而简化了错误处理逻辑。 - 上下文取消:
errgroup
支持与context
包一起使用。当一个 goroutine 返回错误时,errgroup
可以取消所有其他 goroutine 的执行,避免不必要的计算和资源浪费。
一个简单的例子可以帮助理解 errgroup
的使用:
package main
import (
"context"
"fmt"
"golang.org/x/sync/errgroup"
"net/http"
)
func main() {
// 创建一个 errgroup 和一个带有取消功能的上下文
g, ctx := errgroup.WithContext(context.Background())
urls := []string{
"http://example.com",
//"http://example11111.com",
"http://example.net",
"http://example.org",
}
for _, url := range urls {
// 启动一个 goroutine 来抓取每个 URL
url := url // 创建一个新的变量以避免闭包问题
g.Go(func() error {
// 使用 ctx 发起 HTTP 请求
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("error fetching %s: %s", url, resp.Status)
}
fmt.Printf("Successfully fetched %s\n", url)
return nil
})
}
// 等待所有的 goroutine 完成
if err := g.Wait(); err != nil {
fmt.Printf("Error: %v\n", err)
} else {
fmt.Println("All URLs fetched successfully.")
}
}
使用正确地址全部成功
使用错误地址,返回错误,取消其他goroutine