github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/app/bconcurrent/fan_in.go (about) 1 package bconcurrent 2 3 import "reflect" 4 5 // FanInRec 扇入模式 6 func FanInRec[T any](channels ...<-chan T) <-chan T { 7 out := make(chan T, 1) 8 go func() { 9 defer close(out) 10 var cases []reflect.SelectCase 11 for _, channel := range channels { 12 cases = append(cases, reflect.SelectCase{ 13 Dir: reflect.SelectRecv, 14 Chan: reflect.ValueOf(channel), 15 }) 16 } 17 for len(cases) > 0 { 18 i, v, ok := reflect.Select(cases) 19 if !ok { 20 // 监控的channel已经关闭 21 cases = append(cases[:i], cases[i+1:]...) 22 continue 23 } 24 out <- v.Interface().(T) 25 } 26 }() 27 return out 28 } 29 30 // MergeChannel 合并两个channel 31 func MergeChannel[T any](a, b <-chan T) <-chan T { 32 c := make(chan T) 33 go func() { 34 defer close(c) 35 for a != nil || b != nil { 36 select { 37 case v, ok := <-a: 38 if !ok { 39 a = nil 40 continue 41 } 42 c <- v 43 case v, ok := <-b: 44 if !ok { 45 b = nil 46 continue 47 } 48 c <- v 49 } 50 } 51 }() 52 return c 53 }