Go⚡Concurrencyintermediate
Select
Go · Concurrency · Run with go run
Explanation
`select` waits on multiple channel operations simultaneously, executing the first one that is ready. If multiple are ready, it picks one at random. A `default` case makes `select` non-blocking. `select` is the primary tool for timeouts, cancellation, and fan-in patterns.
Real-World Scenario
An API gateway calls two backend services concurrently and uses `select` with a timeout channel: whichever responds first wins; if neither responds within 500ms, the timeout case fires and the gateway returns a 503.
Quick Snippet
snippet.go
func fetchWithTimeout(url string, timeout time.Duration) (string, error) {
resultCh := make(chan string, 1)
go func() {
resultCh <- fetch(url) // assume fetch returns string
}()
select {
case result := <-resultCh:
return result, nil
case <-time.After(timeout):
return "", fmt.Errorf("timeout after %v", timeout)
}
}Full Example
select.go
// Compile: go run select.go
// Output:
// got: fast result
package main
import (
"fmt"
"time"
)
func fetch(label string, delay time.Duration) <-chan string {
ch := make(chan string, 1)
go func() {
time.Sleep(delay)
ch <- label
}()
return ch
}
func main() {
fast := fetch("fast result", 50*time.Millisecond)
slow := fetch("slow result", 500*time.Millisecond)
// select picks whichever channel is ready first
select {
case r := <-fast:
fmt.Println("got:", r)
case r := <-slow:
fmt.Println("got:", r)
case <-time.After(time.Second):
fmt.Println("timeout")
}
}
Run command
go run select.go