github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/prepare/18channeluse/or_channel_rec/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "time" 6 ) 7 8 //递归的方式 分而治之的方式,逐步合并channel,最终返回一个channel 9 func or(channels ...<-chan interface{}) <-chan interface{} { 10 // 递归跳出条件 11 switch len(channels) { 12 case 0: 13 return nil 14 case 1: 15 return channels[0] 16 } 17 18 orDone := make(chan interface{}) 19 go func() { 20 defer close(orDone) 21 22 switch len(channels) { 23 case 2: 24 select { 25 case <-channels[0]: 26 case <-channels[1]: 27 } 28 default: 29 m := len(channels) / 2 30 select { 31 case <-or(channels[:m]...): 32 case <-or(channels[m:]...): 33 } 34 } 35 }() 36 37 return orDone 38 } 39 40 func sig(after time.Duration) <-chan interface{} { 41 c := make(chan interface{}) 42 go func() { 43 defer close(c) 44 time.Sleep(after) 45 }() 46 return c 47 } 48 49 func main() { 50 51 start := time.Now() 52 53 <-or( 54 sig(10*time.Second), 55 sig(20*time.Second), 56 sig(30*time.Second), 57 sig(40*time.Second), 58 sig(5*time.Second), 59 sig(01*time.Minute), 60 ) 61 62 fmt.Printf("done after %v", time.Since(start)) 63 }