Select waits on a group of channels
The select statement waits for multiple send or receive operations simultaneously.
- The statement blocks as a whole until one of the operations becomes unblocked.
- If several cases can proceed, a single one of them will be chosen at random.
// blocks until there's data available on ch1 or ch2
select {
case <-ch1:
fmt.Println("Received from ch1")
case <-ch2:
fmt.Println("Received from ch2")
}
Send and receive operations on a nil
channel block forever.
This can be used to disable a channel in a select statement:
ch1 = nil // disables this channel
select {
case <-ch1:
fmt.Println("Received from ch1") // will not happen
case <-ch2:
fmt.Println("Received from ch2")
}
Default case
The default
case is always able to proceed and runs if all other cases are blocked.
// never blocks
select {
case x := <-ch:
fmt.Println("Received", x)
default:
fmt.Println("Nothing available")
}
Examples
An infinite random binary sequence
As a toy example you can use the random choice among cases that can proceed to generate random bits.
rand := make(chan int)
for {
select {
case rand <- 0: // no statement
case rand <- 1:
}
}
A blocking operation with a timeout
The function time.After
is part of the standard library;
it waits for a specified time to elapse and then sends the current time on the returned channel.
select {
case news := <-AFP:
fmt.Println(news)
case <-time.After(time.Minute):
fmt.Println("Time out: No news in one minute")
}
A statement that blocks forever
A select statement blocks until at least one of it’s cases can proceed. With zero cases this will never happen.
select {}
A typical use would be at the end of the main function in some multithreaded programs. When main returns, the program exits and it does not wait for other goroutines to complete.