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