Question

To quote from the The Go Programming Language Specification:

A "select" statement chooses which of a set of possible communications will proceed. It looks similar to a "switch" statement but with the cases all referring to communication operations.

How can I wait for more than one channel in a case clause, so that only when both channels return the case is executed?

example:

select {

   case <-ch1, <-ch2 ... : //wait for ch1 and ch2 
        // do something 
   case  ..
}
Was it helpful?

Solution

There's no way to wait for multiple channels in the same select case, and there's also no way way to "fallthrough" in select cases, as the documentation describes:

You can easily do something like this via other means, though.

Without select:

This only works if c1 is guaranteed to return despite the availability of c2.

v1 := <-c1
v2 := <-c2

With looping:

This works despite the ordering, but c1 and c2 must only fire once, or it might misbehave:

var v1, v2 int
for i := 0; i < 2; i++ {
    select {
    case v1 = <-c1:
    case v2 = <-c2:
    }
}
// both v1 and v2 are set here

With goroutines:

This works either way, but you lose the ordering of results:

c3 := make(chan int, 2)
go func() { c3 <- (<-c1) }()
go func() { c3 <- (<-c2) }()

first := <-c3
second := <-c3

With sync.WaitGroup:

This works either way:

var wg sync.WaitGroup
var v1, v2 int
wg.Add(2)
go func() {
    v1 = <-c1
    wg.Done()
}()
go func() {
    v2 = <-c2
    wg.Done()
}()
wg.Wait()
// v1 and v2 are both set

And so on. There are certainly other ways. The best one depends on the details of what you're trying to achieve.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top