The idea is to have a variable number of channels in a slice, push each value received through them into a single channel, and close this output channel once the last one of the input channels is closed. Something like this, but for a number of channels more than two:
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
}
}
}
The above code avoids busy looping since there is no default case, which is good (EDIT: it looks like the presence of “, ok” makes the select statement non-blocking and the loop is busy after all. But for the sake of the example, think of the code as if it would block). Could the same kind of functionality also be achieved with an arbitrary number of input channels? Obviously, this could be done by reducing the slice pairwise to a single channel, but I would be more interested in a simpler solution, if possible.
I believe this snippet does what you’re looking for. I’ve changed the signature so that it’s clear that the inputs and output should only be used for communication in one direction. Note the addition of a
sync.WaitGroup, you need some way for all of the inputs to signal that they have completed, and this is pretty easy.