github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/app/bconcurrent/or_done.go (about)

     1  package bconcurrent
     2  
     3  import "reflect"
     4  
     5  // OrDone 任意channel完成后返回
     6  func OrDone[T any](channels ...<-chan T) <-chan T {
     7  	switch len(channels) {
     8  	case 0:
     9  		// 返回已经关闭的channel 通知各个接受者关闭
    10  		c := make(chan T)
    11  		close(c)
    12  		return c
    13  	case 1:
    14  		return channels[0]
    15  	}
    16  	orDone := make(chan T, 1)
    17  	go func() {
    18  		defer close(orDone)
    19  		var cases []reflect.SelectCase
    20  		for _, channel := range channels {
    21  			cases = append(cases, reflect.SelectCase{
    22  				Dir:  reflect.SelectRecv,
    23  				Chan: reflect.ValueOf(channel),
    24  			})
    25  		}
    26  		// 选择一个可用的
    27  		reflect.Select(cases)
    28  	}()
    29  	return orDone
    30  }