What does this select loop over a cap-1 channel print?
Predict the output, and say what changes if ch were unbuffered.
func main() {
ch := make(chan int, 1)
for i := 0; i < 10; i++ {
select {
case x := <-ch:
print(x)
case ch <- i:
}
}
}
Explain the output and the unbuffered case.
It prints 02468. With capacity 1 on a single goroutine the send and receive cases alternate: on an empty buffer only the send is ready (buffers i, prints nothing); next iteration the buffer is full so only the receive is ready (prints the stored even value). With an unbuffered channel neither case is ever ready on one goroutine, so the program is a fatal error: all goroutines are asleep - deadlock.
- ✗Thinking one
selectpass can both send and receive on the same channel - ✗Forgetting that an unbuffered channel makes both cases block, causing a deadlock
- ✗Calling the deadlock a recoverable panic rather than a fatal runtime error
- →Why does the very first iteration print nothing rather than
0? - →Why is
all goroutines are asleep - deadlocka fatal error and not apanicyou canrecover?
What it prints
02468.
The channel is buffered with capacity 1, and all the code runs in one goroutine. In a select a case is ready only if its operation can proceed immediately:
i=0: buffer empty → receive not ready, send ready. Store0. No print.i=1: buffer full ([0]) → send not ready, receive ready. Print0, buffer empties.i=2: buffer empty → store2.i=3: buffer full ([2]) → print2.- … and so on → it prints
0, 2, 4, 6, 8.
The unbuffered case
Change it to make(chan int) and, on a single goroutine, neither case is ready: the send has no receiver, the receive has no sender. A select with no default blocks, and all goroutines are asleep:
fatal error: all goroutines are asleep - deadlock!
This is a fatal runtime error, not a panic — it cannot be caught with recover.