这个想法是在一个 slice 中拥有可变数量的 channel ,将通过它们接收到的每个值推送到单个 channel 中,并在最后一个输入 channel 关闭后关闭此输出 channel 。像这样,但对于两个以上的 channel :
func multiplex(cin1, cin2, cout chan int) {
n := 2
for {
select {
case v, ok := <-cin1:
if ok {
cout <- v
} else {
n -= 1
}
case v, ok := <-cin2:
if ok {
cout <- v
} else {
n -= 1
}
}
if n == 0 {
close(cout)
break
}
}
}
上面的代码避免了忙循环,因为没有 default
情况,这很好(编辑:看起来“,ok”的存在使得选择语句非阻塞,循环是毕竟很忙。但是为了这个例子,把代码想象成它会阻塞)。是否也可以通过任意数量的输入 channel 来实现相同的功能?显然,这可以通过将 slice 成对地减少到单个 channel 来完成,但如果可能的话,我会对更简单的解决方案更感兴趣。
最佳答案
我相信这个片段可以满足您的需求。我已经更改了签名,因此很明显输入和输出应该只用于一个方向的通信。注意添加了 sync.WaitGroup
,您需要某种方式让所有输入都表明它们已完成,这很容易。
func combine(inputs []<-chan int, output chan<- int) {
var group sync.WaitGroup
for i := range inputs {
group.Add(1)
go func(input <-chan int) {
for val := range input {
output <- val
}
group.Done()
} (inputs[i])
}
go func() {
group.Wait()
close(output)
} ()
}
关于concurrency - 是否可以将多个 channel 复用为一个?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10979608/