What does the select statement do?
Quick Answer
select lets a goroutine wait on multiple channel operations at once, proceeding with whichever case becomes ready first. If multiple cases are ready simultaneously, Go picks one at random, which prevents any single channel from being unfairly starved. A default case makes the whole select non-blocking — it runs immediately if no other case is ready, instead of waiting. select is the standard tool for implementing timeouts (select on a work channel and a time.After channel), cancellation (select on a work channel and a context.Done() channel), and fan-in patterns that merge multiple input channels into one.
Detailed Answer
select is Go's multiplexer for channel operations, and it shows up constantly in real concurrent code.
Waiting on the first of several channels
select {
case v := <-ch1:
fmt.Println("from ch1:", v)
case v := <-ch2:
fmt.Println("from ch2:", v)
}
Whichever channel has a value ready first wins. If both are ready at the same instant, Go picks randomly between them.
Implementing a timeout
select {
case result := <-workCh:
fmt.Println("got result:", result)
case <-time.After(2 * time.Second):
fmt.Println("timed out")
}
Non-blocking check with default
select {
case v := <-ch:
fmt.Println("received:", v)
default:
fmt.Println("no value ready, moving on")
}
Without default, this select would block until ch had a value. With it, the select returns immediately either way.
Cancellation with context
func worker(ctx context.Context, workCh <-chan int) {
for {
select {
case <-ctx.Done():
return // caller cancelled, stop working
case v := <-workCh:
process(v)
}
}
}
This pattern, select between real work and a cancellation signal, is the standard way to make a long-running goroutine stoppable from the outside.