github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/prepare/18channeluse/or_channel_reflect/main.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "reflect" 6 "time" 7 ) 8 9 /* 10 Go的反射库针对select语句有专门的数据(reflect.SelectCase)和函数(reflect.Select)处理。 11 所以我们可以利用反射“随机”地从一组可选的channel中接收数据,并关闭输出channel。 12 */ 13 func or(chans ...<-chan interface{}) <-chan interface{} { 14 switch len(chans) { 15 case 0: 16 return nil 17 case 1: 18 return chans[0] 19 } 20 orDone := make(chan interface{}) 21 go func() { 22 defer close(orDone) 23 var cases []reflect.SelectCase 24 for _, c := range chans { 25 cases = append(cases, reflect.SelectCase{ 26 Dir: reflect.SelectRecv, 27 Chan: reflect.ValueOf(c), 28 }) 29 } 30 reflect.Select(cases) 31 }() 32 return orDone 33 } 34 35 func main() { 36 sig := func(after time.Duration) <-chan interface{} { 37 c := make(chan interface{}) 38 go func() { 39 defer close(c) 40 time.Sleep(after) 41 }() 42 return c 43 } 44 45 start := time.Now() 46 <-or( 47 sig(10*time.Second), 48 sig(3*time.Second), 49 sig(20*time.Second), 50 sig(30*time.Second), 51 sig(40*time.Second), 52 sig(01*time.Minute), 53 ) 54 fmt.Printf("done after %v", time.Since(start)) 55 }