Go channel 数据聚合

一个数据聚合模块的工作协程将多个数据流合为一个数据流(就是指有多个源 channel 输入、一个目的 channel 输出的情况)。

下面这个函数将任意数量的数据流合为一个。

e.g.

通过每个 goroutine 处理一个 channel 的方式来实现。

go 复制代码
func Aggregator(chs ...<-chan any) <-chan any {
 out := make(chan any)
 var wg sync.WaitGroup
 for _, ch := range chs {
  wg.Add(1)
  ch := ch
  go func() {
   defer wg.Done()
   for v := range ch {
    out <- v
   }
  }()
 }
 go func() {
  wg.Wait()
  close(out)
 }()
 return out
}

e.g.

通过反射的方式来实现,主要就是构造出 SelectCase slice,然后传递给 reflect.Select 语句。

go 复制代码
func AggregatorReflect(chs ...<-chan any) <-chan any {
 out := make(chan any)
 go func() {
  defer close(out)
  // 构造 SelectCase slice
  var cases []reflect.SelectCase
  for _, ch := range chs {
   cases = append(cases, reflect.SelectCase{
    Dir:  reflect.SelectRecv,
    Chan: reflect.ValueOf(ch),
   })
  }
  // 循环,从 cases 中选择一个可用的
  for len(cases) > 0 {
   i, v, ok := reflect.Select(cases)
   if !ok { // 此通道关闭并且它的缓冲队列中为空
    cases = append(cases[:i], cases[i+1:]...)
    continue
   }
   out <- v.Interface()
  }
 }()
 return out
}
相关推荐
行百里er11 分钟前
Redis 模块——JSON、向量搜索与时序
redis·后端
一条泥憨鱼1 小时前
【从0开始学习计算机网络】| ARP 协议:地址解析,ARP 欺骗,链路层寻址
网络·后端·学习·计算机网络
2501_933923251 小时前
SpringCloud组件:Eureka服务注册与发现
java·开发语言·后端·spring cloud·eureka
leikooo1 小时前
ARTS 1011: 双堆动态对顶求中位数、IPC 注入与空密码串联接管账户与程序从不做决策
后端
合尘猫1 小时前
AI 项目上线就停:一次事件循环阻塞的完整排查过程
人工智能·后端·python
Re_zero2 小时前
一次 SSE 断流排查:PrintWriter 吞掉了我的 IOException
java·后端
1m555555552 小时前
RAG 工程实战(四):明明召回了正确知识,为什么最终 Top-K 还是漏了?
后端
我是人✓2 小时前
Java核心语法:作用域、循环与大数值处理
java·开发语言·后端
newerp2 小时前
GC Pacer 调优算法:GOGC、GOMEMLIMIT 与容器 OOM 防御
后端·程序员·go