Go: Select explained

The select statement waits for multiple send or receive opera­tions simul­taneously.

// 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")
}
  • 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.

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, "from ch")
default:
	fmt.Println("Nothing available on ch")
}

More examples

// An infinite random binary sequence
rand := make(chan int)
for {
	select {
	case rand <- 0: // Note: no statement
	case rand <- 1:
	}
}
// A blocking operation with a timeout
select {
case news := <-AFP:
	fmt.Println(news)
case <-time.After(time.Minute):
	fmt.Println("Time out: No news in one minute")
}

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.

// Block forever
select {}

A select statement blocks until at least one of it’s cases can proceed. With zero cases this will never happen.

Comments