If we add a default case to the previous example, the result of the application execution will be very different, particularly if we change select:
select {
case v := <-ch2:
fmt.Println("ch2 got a", v)
case ch1 <- b:
fmt.Println("ch1 got a", b)
default:
fmt.Println("too slow")
}
The full example is available at https://play.golang.org/p/F1aE7ImBNFk.
The select statement will always choose the default statement. This happens because the goroutines are not picked up by the scheduler yet, when the select statement is executed. If we add a very small pause (using time.Sleep) before the select switch, we will have the scheduler pick at least one goroutine and we will then have one of the two operations executed:
func main() {
ch1, ch2 := make(chan int), make(chan int)
a, b := 2, 10
for i := 0; i < 10; i++ {
go func() { <-ch1 }()
go func() { ch2 <- a }()
time.Sleep(time.Nanosecond)
select {
case ch1 <- b:
fmt.Println("ch1 got a", b)
case v := <-ch2:
fmt.Println("ch2 got a", v)
default:
fmt.Println("too slow")
}
}
}
The full example is available at https://play.golang.org/p/-aXc3FN6qDj.
In this case, we will have a mixed set of operations executed, depending on which one gets picked up by the Go scheduler.