What does this print? (select evaluation order)
Question 202HardGo 1.22 to 1.25
package main
import "fmt"
func val(s string, v int) int { fmt.Println("eval", s); return v }
func chn(s string, c chan int) chan int { fmt.Println("chan", s); return c }
func main() {
a := make(chan int, 1)
b := make(chan int, 1)
b <- 0
select {
case chn("a", a) <- val("a", 1):
fmt.Println("sent a")
case <-chn("b", b):
fmt.Println("recv b")
}
}
Output, where the first three lines are deterministic:
chan a
eval a
chan b
sent a // or "recv b": both are ready, chosen at random
The spec says that on entering a select, the channel operands of receives and the channel and value expressions of sends are all evaluated exactly once, in source order, whichever case ends up chosen. Only then does the select choose among the ready cases. So side effects in case expressions always happen, including for cases that aren't picked. The left-hand side of a receive assignment (case x[i()] = <-c) is evaluated only if that case is selected.
More on Channels & select
- Q200What's the difference between
time.Tickerand repeatedtime.After? What happens if the consumer is slow? - Q201How do you do a non-blocking send or receive?
- Q203How would you implement a semaphore / bounded concurrency with channels?
- Q204Implement a worker pool with result collection and proper shutdown.
- Q205What is a goroutine leak caused by channels? Show one and fix it.
- Q206Why is
chan struct{}preferred for signaling, and how doescloseact as a broadcast?