// Created on savesnippets.com ยท https://savesnippets.com/pgYPYbo8swnuls // go get golang.org/x/sync/errgroup package main import ( "context" "fmt" "net/http" "golang.org/x/sync/errgroup" ) func fetchAll(ctx context.Context, urls []string) error { g, ctx := errgroup.WithContext(ctx) // ctx cancels when first error happens g.SetLimit(8) // optional: cap concurrency for _, url := range urls { url := url // capture per iteration g.Go(func() error { req, _ := http.NewRequestWithContext(ctx, "GET", url, nil) resp, err := http.DefaultClient.Do(req) if err != nil { return fmt.Errorf("get %s: %w", url, err) } resp.Body.Close() if resp.StatusCode >= 400 { return fmt.Errorf("get %s: status %d", url, resp.StatusCode) } fmt.Println("OK", url) return nil }) } return g.Wait() // returns first error or nil } func main() { err := fetchAll(context.Background(), []string{ "https://example.com", "https://golang.org", }) if err != nil { fmt.Println("failed:", err) } }