Errgroup
Concurrent work with first-error cancellation using errgroup.
package main
import (
"context"
"fmt"
"time"
"golang.org/x/sync/errgroup"
)
func fetchURL(ctx context.Context, url string) error {
// Simulate fetching
select {
case <-time.After(200 * time.Millisecond):
if url == "https://fail.example.com" {
return fmt.Errorf("failed to fetch %s", url)
}
fmt.Println("fetched:", url)
return nil
case <-ctx.Done():
return ctx.Err()
}
}
func main() {
urls := []string{
"https://go.dev",
"https://pkg.go.dev",
"https://fail.example.com",
"https://example.com",
}
g, ctx := errgroup.WithContext(context.Background())
g.SetLimit(2) // max 2 concurrent
for _, url := range urls {
url := url
g.Go(func() error {
return fetchURL(ctx, url)
})
}
if err := g.Wait(); err != nil {
fmt.Println("error:", err)
} else {
fmt.Println("all succeeded")
}
}