patterngoModerate
select with default for non-blocking channel operations
Viewed 0 times
select defaultnon-blocking channelchannel polltime.After leakcontext done checkselect statement
Problem
Checking whether a channel has a value or is done without blocking the current goroutine requires a non-blocking receive.
Solution
Use select with a default case:
// Non-blocking receive
select {
case v := <-ch:
fmt.Println("received", v)
default:
fmt.Println("no value ready")
}
// Non-blocking send
select {
case ch <- value:
fmt.Println("sent")
default:
fmt.Println("channel full or no receiver")
}
// Poll done channel without blocking
func isContextDone(ctx context.Context) bool {
select {
case <-ctx.Done():
return true
default:
return false
}
}
// Timeout with select
select {
case result := <-work:
handle(result)
case <-time.After(5 * time.Second):
log.Println("timeout")
}Why
select evaluates all cases simultaneously. A default case makes the entire select non-blocking — if no channel is ready, default executes immediately.
Gotchas
- time.After leaks the underlying timer until it fires — for repeated timeouts use time.NewTimer and defer t.Stop()
- select with multiple ready channels picks one at random — do not rely on ordering
- A select with no cases (select{}) blocks forever — use it as a program-end park if needed
Revisions (0)
No revisions yet.