What happens if you send on a closed channel inside a select with a default?
Question 210HardGo 1.22 to 1.25
ch := make(chan int, 1)
close(ch)
select {
case ch <- 1:
fmt.Println("sent")
default:
fmt.Println("default")
}
It panics with send on closed channel. It does not fall through to default. A send case on a closed channel counts as "ready" (it can proceed immediately), and proceeding means panicking. select gives you no protection here.
A related trap: people sometimes try to write a "safe send" like this:
func trySend(ch chan int, v int) (ok bool) {
defer func() {
if recover() != nil { ok = false }
}()
ch <- v
return true
}
It works, but it's a code smell that signals broken ownership. The right fix is to make sure only the sender side closes, after all sends are done, or to have senders select on a separate done channel instead of ever closing the data channel. Interviewers ask this to see whether you know that closed-channel semantics differ between send (panic) and receive (zero value).
More on Channels & select
- Q208Channels or mutexes: how do you decide?
- Q209Explain the pipeline pattern and how to cancel it properly.
- Q211Does an unbuffered channel give a happens-before guarantee? What does the memory model say about channels?
- Q212Implement a generic "first response wins" (hedged request / race) function.
- Q213What does this print? (request/response over a channel of channels)
- Q214How would you implement rate limiting using channels?