背景
有了泛型可以做到复用,比如sort,filter,map,reduce等常用方法,这里举个ch的例子
我们写go时候经常会进行ch的fanin,fanout操作,但是没有泛型时候,没办法写针对任何类型的(类型安全,不考虑类型安全的话可以传入interface{}然后通过反射来做到)
例子
package main
import (
"fmt"
"reflect"
)
func FanOut[T any](chs ...chan T) chan<- T {
ret := make(chan T)
recvChValue := reflect.ValueOf(ret)
sendChValues := make([]reflect.Value, 0, len(chs))
for _, ch := range chs {
value := reflect.ValueOf(ch)
sendChValues = append(sendChValues, value)
}
go func() {
for {
value, ok := recvChValue.Recv()
for _, sendChValue := range sendChValues {
if !ok {
sendChValue.Close()
continue
}
sendChValue.Send(value)
}
if !ok {
return
}
}
}()
return ret
}
func FanIn[T any](chs ...chan T) <-chan T {
ret := make(chan T)
cases := make([]reflect.SelectCase, 0, len(chs))
for _, ch := range chs {
value := reflect.ValueOf(ch)
item := reflect.SelectCase{
Dir: reflect.SelectRecv,
Chan: value,
}
cases = append(cases, item)
}
go func() {
for {
chosen, recvValue, ok := reflect.Select(cases)
if !ok {
curCases := make([]reflect.SelectCase, 0, len(chs))
for idx, each := range cases {
if chosen == idx {
curCases = append(curCases, cases[idx+1:]...)
break
}
curCases = append(curCases, each)
}
if len(curCases) == 0 {
close(ret)
return
}
cases = curCases
continue
}
ret <- recvValue.Interface().(T)
}
}()
return ret
}
func main() {
fanInCh1 := make(chan int, 1)
fanInCh2 := make(chan int, 1)
fanInCh := FanIn(fanInCh1, fanInCh2)
fanInCh1 <- 1
fmt.Println(<-fanInCh)
fanInCh2 <- 2
fmt.Println(<-fanInCh)
close(fanInCh1)
fanInCh2 <- 3
fmt.Println(<-fanInCh)
close(fanInCh2)
fmt.Println(<-fanInCh)
fanOutCh1 := make(chan int, 1)
fanOutCh2 := make(chan int, 1)
fanOutCh := FanOut(fanOutCh1, fanOutCh2)
fanOutCh <- 1
fmt.Println(<-fanOutCh1, <-fanOutCh2)
close(fanOutCh)
fmt.Println(<-fanOutCh1, <-fanOutCh2)
}