Breakdown of “select” statement in Go
Alright, lets take this great example to understand how the `select` statement works in Go. Let’s go step-by-step:
Channels Creation in main :
c := make(chan int)
quit := make(chan int)
- c will be used for sending Fibonacci sequence numbers.
- quit will be used to signal when to stop generating Fibonacci numbers.
2. Goroutine in main :
go func() {
for i := 0; i < 10; i++ {
fmt.Println(<-c)
}
quit <- 0
}()
- This anonymous goroutine is started in the background.
- It waits to receive 10 Fibonacci numbers from the channel `c` and prints them.
- After printing 10 numbers, it sends a value (0 in this case, but the actual value isn’t used or checked) to the quit channel, signaling that it’s done.
3. fibonacci function :
- It initializes two values `x` and `y` to `0` and `1`, the first two numbers in the Fibonacci sequence.
- It enters an infinite `for` loop, and within this loop, there’s a `select` statement.
4. select Statement :
select {
case c <- x:
x, y = y, x+y
case <-quit:
fmt.Println("quit")
return
}
- The `select` statement allows a goroutine to wait on multiple communication operations. It’s similar to a `switch` statement, but for channels.
- The `select` will block until one of its cases can execute, then it will execute that case. If multiple cases could proceed, then one case is chosen at random to execute.
- In this example, there are two cases:
1. Sending the current Fibonacci number (`x`) to channel `c`.
2. Receiving a value from the `quit` channel.
5. Working of the select :
- If the main goroutine (specifically, the anonymous one) is ready to receive a value on `c`, the first case will execute: the current Fibonacci number (`x`) is sent over channel `c`, and then the next Fibonacci number is calculated.
- If a value is sent on the `quit` channel (which happens after the anonymous goroutine has received and printed 10 Fibonacci numbers), the second case will execute, printing “quit” and then exiting the `fibonacci` function.
6. Back to the main function :
- After starting the anonymous goroutine, `main` calls the `fibonacci` function directly.
- The `fibonacci` function will keep generating numbers until it receives a signal on the `quit` channel.
- Once “quit” is printed and the `fibonacci` function returns, the `main` function also finishes execution and the program ends.
Lets Visualise
Main Goroutine G1
| |
| starts G1 |
|----------------------------->|
| |
calls fibonacci() |
enters infinite loop |
waiting on channels |
| |
| |
| reads from c
| 10 times
| |
Main Goroutine G1
| |
| |
sends 0 to c |
|<-----------------------------|
| |
sends 1 to c |
|<-----------------------------|
| |
... |
... |
... |
... |
sends 34 to c |
|<-----------------------------|
| |
waits on select |
| |
| sends to quit
|<-----------------------------|
prints "quit" |
and exits fibonacci() |
| |
Main Goroutine ends |
In summary
The `select` statement provides a way to handle multiple channels simultaneously. The `fibonacci` function keeps generating Fibonacci numbers, but can be interrupted (and told to exit) by sending a value on the `quit` channel. The `main` function sets this all up, creating a goroutine that prints the first 10 Fibonacci numbers and then signals the generator to quit.