mirror of
https://github.com/crazybber/awesome-patterns.git
synced 2024-11-26 23:06:03 +03:00
68 lines
1.2 KiB
Go
68 lines
1.2 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"sync"
|
||
|
)
|
||
|
|
||
|
func main() {
|
||
|
in := gen(2, 3)
|
||
|
|
||
|
// Distribute the sq work across two goroutines that both read from in.
|
||
|
c1 := sq(in)
|
||
|
c2 := sq(in)
|
||
|
|
||
|
// Consume the merged output from c1 and c2.
|
||
|
for n := range merge(c1, c2) {
|
||
|
fmt.Println(n) // 4 then 9, or 9 then 4
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func gen(nums ...int) <-chan int {
|
||
|
out := make(chan int, len(nums))
|
||
|
go func() {
|
||
|
for _, n := range nums {
|
||
|
out <- n
|
||
|
}
|
||
|
close(out)
|
||
|
}()
|
||
|
return out
|
||
|
}
|
||
|
|
||
|
func sq(in <-chan int) <-chan int {
|
||
|
out := make(chan int)
|
||
|
go func() {
|
||
|
for n := range in {
|
||
|
out <- n * n
|
||
|
}
|
||
|
close(out)
|
||
|
}()
|
||
|
return out
|
||
|
}
|
||
|
|
||
|
func merge(cs ...<-chan int) <-chan int {
|
||
|
var wg sync.WaitGroup
|
||
|
out := make(chan int, 1) // enough space for the unread inputs
|
||
|
|
||
|
// Start an output goroutine for each input channel in cs. output
|
||
|
// copies values from c to out until c is closed, then calls wg.Done.
|
||
|
output := func(c <-chan int) {
|
||
|
for n := range c {
|
||
|
out <- n
|
||
|
}
|
||
|
wg.Done()
|
||
|
}
|
||
|
wg.Add(len(cs))
|
||
|
for _, c := range cs {
|
||
|
go output(c)
|
||
|
}
|
||
|
|
||
|
// Start a goroutine to close out once all the output goroutines are
|
||
|
// done. This must start after the wg.Add call.
|
||
|
go func() {
|
||
|
wg.Wait()
|
||
|
close(out)
|
||
|
}()
|
||
|
return out
|
||
|
}
|