github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/blog/content/pipelines/sqdone2.go (about) 1 // +build OMIT 2 3 package main 4 5 import ( 6 "fmt" 7 "sync" 8 ) 9 10 // gen sends the values in nums on the returned channel, then closes it. 11 func gen(nums ...int) <-chan int { 12 out := make(chan int, len(nums)) 13 for _, n := range nums { 14 out <- n 15 } 16 close(out) 17 return out 18 } 19 20 // sq receives values from in, squares them, and sends them on the returned 21 // channel, until in is closed. Then sq closes the returned channel. 22 func sq(in <-chan int) <-chan int { 23 out := make(chan int) 24 go func() { 25 for n := range in { 26 out <- n * n 27 } 28 close(out) 29 }() 30 return out 31 } 32 33 // merge receives values from each input channel and sends them on the returned 34 // channel. merge closes the returned channel after all the input values have 35 // been sent. 36 func merge(done <-chan struct{}, cs ...<-chan int) <-chan int { 37 var wg sync.WaitGroup 38 out := make(chan int) 39 40 // Start an output goroutine for each input channel in cs. output 41 // copies values from c to out until c or done is closed, then calls 42 // wg.Done. 43 output := func(c <-chan int) { 44 for n := range c { 45 select { 46 case out <- n: 47 case <-done: // HL 48 } 49 } 50 wg.Done() 51 } 52 wg.Add(len(cs)) 53 for _, c := range cs { 54 go output(c) 55 } 56 57 // Start a goroutine to close out once all the output goroutines are 58 // done. This must start after the wg.Add call. 59 go func() { 60 wg.Wait() 61 close(out) 62 }() 63 return out 64 } 65 66 func main() { 67 in := gen(2, 3) 68 69 // Distribute the sq work across two goroutines that both read from in. 70 c1 := sq(in) 71 c2 := sq(in) 72 73 // Consume the first value from output. 74 done := make(chan struct{}) // HL 75 out := merge(done, c1, c2) // HL 76 fmt.Println(<-out) // 4 or 9 77 78 // Tell the remaining senders we're leaving. 79 close(done) // HL 80 }