package main import ( "bufio" "fmt" "os" "sync" "time" ) func expensive(worker int, task string) error { time.Sleep(250 * time.Millisecond) return fmt.Errorf("worker %d is done with %q", worker, task) } func worker(id int, work chan string, results chan error, wg *sync.WaitGroup) { defer wg.Done() for { i, ok := <-work if !ok { return } results <- expensive(id, i) } } func main() { work := make(chan string) results := make(chan error) numWorkers := 4 wwg := &sync.WaitGroup{} wg := &sync.WaitGroup{} for w := 0; w < numWorkers; w++ { wwg.Add(1) go worker(w, work, results, wwg) } s := bufio.NewScanner(os.Stdin) go func(wg *sync.WaitGroup) { for s.Scan() { wg.Add(1) work <- s.Text() } if err := s.Err(); err != nil { panic(err) } close(work) }(wg) go func() { wwg.Wait() wg.Wait() close(results) }() for e := range results { fmt.Printf("received: %+v\n", e) wg.Done() } }