test script
1func gen(nums ...int) <-chan int {
2 out := make(chan int)
3 go func() {
4 for _, n := range nums {
5 out <- n
6 }
7 close(out)
8 }()
9 return out
10}
11func sq(in <-chan int) <-chan int {
12 out := make(chan int)
13 go func() {
14 for n := range in {
15 out <- n * n
16 }
17 close(out)
18 }()
19 return out
20}
21
22func merge(cs ...<-chan int) <-chan int {
23 var wg sync.WaitGroup
24 out := make(chan int)
25
26 // Start an output goroutine for each input channel in cs. output
27 // copies values from c to out until c is closed, then calls wg.Done.
28 output := func(c <-chan int) {
29 for n := range c {
30 out <- n
31 }
32 wg.Done()
33 }
34 wg.Add(len(cs))
35 for _, c := range cs {
36 go output(c)
37 }
38
39 // Start a goroutine to close out once all the output goroutines are
40 // done. This must start after the wg.Add call.
41 go func() {
42 wg.Wait()
43 close(out)
44 }()
45 return out
46}
47
48func TestFan(t *testing.T) {
49 x := []int{0}
50 for i := 1; i < 10000; i++ {
51 x = append(x, i)
52 }
53 st := time.Now().UnixMicro()
54 c := gen(x...)
55
56 out := []<-chan int{}
57 for i := 0; i < 10; i++ {
58 out = append(out, sq(c))
59 }
60
61 // Consume the output.
62 for n := range merge(out...) {
63 fmt.Println(n) // 4 then 9, or 9 then 4
64 }
65 t1 := time.Now().UnixMicro() - st
66
67 fmt.Println("=======")
68 st = time.Now().UnixMicro()
69 var wg sync.WaitGroup
70 wg.Add(len(x))
71 for _, i := range x {
72 go func(x int) {
73 defer wg.Done()
74 fmt.Println(x * x)
75 }(i)
76 }
77 wg.Wait()
78 t2 := time.Now().UnixMicro() - st
79
80 fmt.Printf("===%d vs %d", t1, t2)
81 assert.Assert(t, t1 < t2)
82}
83
84// performace 1:4
85