Use errgroup.WithContext to create a group that cancels all goroutines when the first one fails, then add tasks with g.Go and wait for completion with g.Wait.
package main
import (
"context"
"fmt"
"golang.org/x/sync/errgroup"
)
func main() {
ctx := context.Background()
g, ctx := errgroup.WithContext(ctx)
for i := 0; i < 5; i++ {
i := i
g.Go(func() error {
select {
case <-ctx.Done():
return ctx.Err()
default:
fmt.Println(i)
}
return nil
})
}
if err := g.Wait(); err != nil {
fmt.Println("Error:", err)
}
}