github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/blog/content/pipelines/sqleak.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 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() 49 } 50 wg.Add(len(cs)) 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() 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 first value from output. 72 out := merge(c1, c2) 73 fmt.Println(<-out) // 4 or 9 74 return 75 // Since we didn't receive the second value from out, 76 // one of the output goroutines is hung attempting to send it. 77 }