The select statement in Go allows multiple goroutine to wait on multiple communication operations. It is used to execute a channel among many options.
Overview
The select statement is similar go switch statement but this is specifically for channels. The select statement makes goroutine wait on multiple communication operations. In this, each case statement waits for a send or receive operation from a channel. The select statement blocks until any of the case statements are ready. If there is a situation when there are multiple case statements ready, then it selects one randomly and proceeds.
Syntax
The syntax for select statement looks like this.
1select {
2 case channel_send_receive:
3 // statements
4 case channel_send_receive:
5 // statements
6 default:
7 // optional block
8}
Examples
The select statement with channels and goroutine become a powerful tool for managing synchronization and concurrency. In select statement, the default case will be executed if none of the case statements have send or receive operation ready. This helps make the select statement non-blocking. If all case statements are blocked, the default statement will be executed.
1package main
2
3import (
4 "fmt"
5)
6
7func main() {
8 ch1 := make(chan string)
9 ch2 := make(chan string)
10
11 go sendOne(ch1)
12 go sendTwo(ch2)
13
14 select {
15 case value1 := <-ch1:
16 fmt.Println(value1)
17 case value2 := <-ch2:
18 fmt.Println(value2)
19 default:
20 fmt.Println("Default")
21 }
22}
23
24func sendOne(ch chan string) {
25 ch <- "One"
26}
27
28func sendTwo(ch chan string) {
29 ch <- "Two"
30}
In this case, because the goroutine takes some time to execute, we almost always get Default as the output. In order to allow the goroutine to execute, we have to provide some delay before the select statement.
1func main() {
2 ch1 := make(chan string)
3 ch2 := make(chan string)
4
5 go sendOne(ch1)
6 go sendTwo(ch2)
7
8 time.Sleep(1 * time.Second)
9 select {
10 case value1 := <-ch1:
11 fmt.Println(value1)
12 case value2 := <-ch2:
13 fmt.Println(value2)
14 default:
15 fmt.Println("Default")
16 }
17}
In above code snippet, I have added 1 second sleep time before the select statement. This gives enough time for both goroutine sendOne and sendTwo to execute. Because these two goroutine execute independent of each other, the output of the program is non-deterministic. Sometimes it will output One and sometimes it will be Two.
Another important consideration is that we can use break statement in the case blocks to terminate the select statement.
The switch statement is non-blocking whereas the select statements can block as they are using channels. The switch statement is deterministic because it goes in sequence whereas the select statement is not deterministic.


Comments