package main import ( "flag" "fmt" "sync" "time" ) type Ball struct{ hits int } func main() { numSecs := flag.Int("s", 1, "Number of seconds game should last") flag.Parse() game(*numSecs) } func game(numSecs int) { var wg sync.WaitGroup p0 := make(chan Ball) p1 := player(1, &wg, p0) p2 := player(2, &wg, p1) t := time.Tick(time.Duration(numSecs) * time.Second) p0 <- Ball{} loop: for b := range p2 { select { case p0 <- b: case <-t: break loop } } // This sets off a chain reaction that closes the other // p-channels (p1, p2, etc.) close(p0) wg.Wait() // If any of these prints out, we know we did something wrong. for range p0 { fmt.Println("P0") } for range p1 { fmt.Println("P1") } for range p2 { fmt.Println("P2") } fmt.Println("Done for real!") } func player(id int, wg *sync.WaitGroup, input <-chan Ball) <-chan Ball { out := make(chan Ball) wg.Go(func() { defer func() { close(out) fmt.Printf("(%d) finished\n", id) }() fmt.Printf("(%d) started\n", id) for b := range input { b.hits++ fmt.Printf("(%d) %d\n", id, b.hits) time.Sleep(100 * time.Millisecond) out <- b } }) return out }