type SelectCase struct { Dir SelectDir // direction of case Chan Value // channel to use (for send or receive) Send Value // value to send (for send) }
orDone := make(chaninterface{}) gofunc() { deferclose(orDone) // 利用反射构建SelectCase,这里是读取 var cases []reflect.SelectCase for _, c := range channels { cases = append(cases, reflect.SelectCase{ Dir: reflect.SelectRecv, Chan: reflect.ValueOf(c), }) }
// 随机选择一个可用的case reflect.Select(cases) }()
return orDone }
性能差异
这两种都可以支持大量chan的信号监听,那性能差异大么
虽说递归开销肯定不小,反射也不一定效率高,拿个压测来试试吧
先构造一下chan
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
funcAsStream(done <-chanstruct{}, values ...interface{}) <-chaninterface{} { s := make(chaninterface{}) gofunc() { // 退出时关闭chan deferclose(s) for _, v := range values { select { case <-done: return case s <- v: } } }() return s }
var funcs = []struct { name string f func(...<-chaninterface{}) <-chaninterface{} }{ {"reflection", OrInReflect}, {"recursion", OrRecur}, } funcBenchmarkOr(b *testing.B) { for _, f := range funcs { for n := 8; n <= 1024; n *= 2 { b.Run(fmt.Sprintf("%s/%d", f.name, n), func(b *testing.B) { for i := 0; i < b.N; i++ { b.StopTimer() done := make(chanstruct{}) deferclose(done) streams := make([]<-chaninterface{}, n) for i := range streams { streams[i] = AsStream(done, []interface{}{1}) } b.StartTimer() <-f.f(streams...) } }) } } }