What does each channel operation do on nil, open, and closed channels?
Question 498MediumGo 1.22 to 1.25
This table comes up in almost every senior interview:
Operation nil channel open channel closed channel
send ch<-v blocks forever blocks/succeeds PANIC: send on closed channel
recv <-ch blocks forever blocks/succeeds zero value, ok=false (immediately,
after draining any buffered values)
close(ch) PANIC succeeds PANIC: close of closed channel
len/cap 0 current/capacity buffered count left / capacity
Puzzle:
ch := make(chan int, 2)
ch <- 1
ch <- 2
close(ch)
for v := range ch {
fmt.Print(v, " ") // 1 2
}
v, ok := <-ch
fmt.Println(v, ok) // 0 false
Buffered values can still be received after close. Only then does the channel report closed. Design rules the interviewer wants to hear: only the sender closes, and only when receivers need to know that no more values are coming. With several senders, coordinate through a sync.WaitGroup and close from one place, or signal with a separate done channel or context. Never close a channel just to "free" it, because the garbage collector reclaims unreachable channels.
More on Tricky Output & Code-Review Puzzles
- Q496Why does this loop spin at 100% CPU after one channel closes?
- Q497What does this select print, and where does the break go?
- Q499Which of these deadlock, and why does Go detect some deadlocks but not others?
- Q500Is msg guaranteed to print "hello"? Compare unbuffered and buffered channels.
- Q501Code review: why does this timeout wrapper leak goroutines?
- Q502Which of these recover calls actually stop the panic?