github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/blog/content/pipelines/sqbuffer.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(cs ...<-chan int) <-chan int { 37 var wg sync.WaitGroup 38 out := make(chan int, 1) // enough space for the unread inputs 39 // ... the rest is unchanged ... 40 41 // Start an output goroutine for each input channel in cs. output 42 // copies values from c to out until c is closed, then calls wg.Done. 43 output := func(c <-chan int) { 44 for n := range c { 45 out <- n 46 } 47 wg.Done() 48 } 49 wg.Add(len(cs)) 50 for _, c := range cs { 51 go output(c) 52 } 53 54 // Start a goroutine to close out once all the output goroutines are 55 // done. This must start after the wg.Add call. 56 go func() { 57 wg.Wait() 58 close(out) 59 }() 60 return out 61 } 62 63 func main() { 64 in := gen(2, 3) 65 66 // Distribute the sq work across two goroutines that both read from in. 67 c1 := sq(in) 68 c2 := sq(in) 69 70 // Consume the first value from output. 71 out := merge(c1, c2) 72 fmt.Println(<-out) // 4 or 9 73 return 74 // The second value is sent into out's buffer, and all goroutines exit. 75 }