Explain the comma-ok idiom on channel receive. When is it needed and when is for range better?
Question 187MediumGo 1.22 to 1.25
v, ok := <-ch sets ok to false only when the channel is closed and drained. You need it when:
- you are inside a
selectand must notice closure so you can disable the case or exit; - the zero value is a legitimate payload;
- you receive a single value and must tell "real value" apart from "producer gave up".
for {
select {
case v, ok := <-in:
if !ok {
in = nil // disable this case; keep serving others
continue
}
process(v)
case <-ctx.Done():
return
}
}
for v := range ch is the idiomatic way to consume a channel until it closes. It is equivalent to a comma-ok loop that breaks on !ok. The catch is that range can't be combined with cancellation, so if you also need to watch ctx.Done(), use the explicit select form. Note that comma-ok does not tell you whether a receive would block. Go has no "is closed" query, on purpose, because the answer could change right after you got it.
More on Channels & select
- Q185Give the complete table of channel operation behavior for nil, open, and closed channels.
- Q186What does this print? (receiving from a closed buffered channel)
- Q188Who should close a channel, and why? What are the rules?
- Q189How do you safely close a channel that might be closed by multiple goroutines?
- Q190How does
selectchoose among multiple ready cases? Is it fair? - Q191How do you implement a priority select in Go?