package main import ( "fmt" "log" "math/rand" "sync" "github.com/hashicorp/go-multierror" ) func main() { if err := runConcurrently(); err != nil { log.Fatalf("errors occured: %v", err) } log.Printf("all done, no errors") } func runConcurrently() error { intChan := make(chan int) wg := sync.WaitGroup{} workers := 5 errC := make(chan error) // producer wg.Add(1) go func() { defer wg.Done() defer close(intChan) // insert random numbers into the channel for i := 0; i < 30; i++ { intChan <- rand.Intn(100) } }() // consumer for i := 0; i < workers; i++ { wg.Add(1) go func() { defer wg.Done() for { select { case number, ok := <-intChan: if !ok { return } if err := doSomething(number); err != nil { errC <- err } } } }() } go func() { wg.Wait() close(errC) }() var errs *multierror.Error for { select { case err, ok := <-errC: if !ok { return errs.ErrorOrNil() } if err != nil { errs = multierror.Append(errs, err) } } } } func doSomething(i int) error { if i%15 == 0 { return fmt.Errorf("random error: %v", i) } log.Printf("doing something with %d", i) return nil }