Go

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 select and 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

All 38 Channels & select questions