github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/prepare/18channeluse/or_channel/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "time" 6 ) 7 8 // refer to https://github.com/kat-co/concurrency-in-go-src/blob/master/concurrency-patterns-in-go/the-or-channel/fig-or-channel.go 9 func or(channels ...<-chan interface{}) <-chan interface{} { 10 switch len(channels) { 11 case 0: 12 return nil 13 case 1: 14 return channels[0] 15 } 16 // 分治思想, 两个channel合成1个 17 orDone := make(chan interface{}) 18 go func() { 19 defer close(orDone) 20 21 switch len(channels) { 22 case 2: 23 select { 24 case <-channels[0]: 25 case <-channels[1]: 26 } 27 default: //>=3 28 select { 29 case <-channels[0]: 30 case <-channels[1]: 31 case <-channels[2]: 32 case <-or(append(channels[3:], orDone)...): 33 } 34 } 35 }() 36 return orDone 37 } 38 39 func sig(after time.Duration) <-chan interface{} { 40 c := make(chan interface{}) 41 go func() { 42 defer close(c) 43 time.Sleep(after) 44 }() 45 return c 46 } 47 48 func main() { 49 50 start := time.Now() 51 52 <-or( 53 sig(20*time.Second), 54 sig(30*time.Second), 55 sig(5*time.Second), 56 sig(40*time.Second), 57 sig(50*time.Second), 58 sig(01*time.Minute), 59 sig(3*time.Second), 60 ) 61 62 fmt.Printf("done after %v", time.Since(start)) 63 }