Today, let’s take a closer look at the usage of SELECT in Go language. It is similar to switch case, with a single usage. It can only be used for channel/channel related operations, and each case corresponds to a channel communication (receiving or sending) process. Select waits until a case communication completes, and then executes the statement corresponding to the case branch
// The syntax is as follows:
select{
case <-ch1:
...
case data := <-ch2:
...
case ch3<-data:
...
default: Default action}Copy the code
Next, let’s look at a few examples to help understand the select model.
1. The simplest example
package main
import (
"fmt"
)
func main(a) {
c1 := make(chan string.1)
c2 := make(chan string.1)
c2 <- "hello"
select {
case msg1 := <-c1:
fmt.Println("c1 received: ", msg1)
case msg2 := <-c2:
fmt.Println("c2 received: ", msg2)
default:
fmt.Println("No data received.")}}Copy the code
C2 received: hello c2 received: hello c2 received: hello
2. Avoid deadlock
Select must hit one of the branches during execution. If all cases are iterated and no case expression is hit, the code branch in default is entered.
But what happens when you don’t write the default branch? The SELECT will then block until a case is hit, and if no hit is made, the SELECT will throw an error in the deadlock, as follows.
package main
import (
"fmt"
)
func main(a) {
c1 := make(chan string.1)
c2 := make(chan string.1)
// c2 <- "hello"
select {
case msg1 := <-c1:
fmt.Println("c1 received: ", msg1)
case msg2 := <-c2:
fmt.Println("c2 received: ", msg2)
// default:
// fmt.Println("No data received.")}}Copy the code
The output is as follows
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [select]:
nginxlog/tools.OutPrintf()
D:/work/perlearn/go_space/total/tools/parasenginx.go:233 +0xc5
main.main()
D:/work/perlearn/go_space/total/main.go:8 +0x17
Process finished with exit code 2
Copy the code
3,There are two ways to solve this problem
One is to get into the habit of writing the default branch when you select, even though you’re not writing any code under default. At this point, the above code will not work
package main
import (
"fmt"
)
func main(a) {
c1 := make(chan string.1)
c2 := make(chan string.1)
// c2 <- "hello"
select {
case msg1 := <-c1:
fmt.Println("c1 received: ", msg1)
case msg2 := <-c2:
fmt.Println("c2 received: ", msg2)
default:}}Copy the code
The other is to make sure that one of the channels can receive data
package main
import (
"fmt"
"time"
)
func main(a) {
c1 := make(chan string.1)
c2 := make(chan string.1)
// Start a coroutine that can send data to the channel
go func(a) {
time.Sleep(time.Second * 1)
c2 <- "hello"} ()select {
case msg1 := <-c1:
fmt.Println("c1 received: ", msg1)
case msg2 := <-c2:
fmt.Println("c2 received: ", msg2)
}
}
Copy the code
4, select randomness
In switch, cases are executed sequentially, but not in SELECT.
func main(a){
c1 := make(chan string.1)
c2 := make(chan string.1)
c1 <- "hello"
c2 <- "123123"
select {
case msg1 := <-c1:
fmt.Println("c1 received: ", msg1)
case msg2 := <-c2:
fmt.Println("c2 received: ", msg2)
}
}
Copy the code
5. Select timeout
When the channel in the case never receives data and there is no default statement, the select will block as a whole, but sometimes we do not want the select to block forever, so we can manually set a timeout
func main(a){
ch1:=make(chan string.1)
ch2:=make(chan string.1)
timeout:=make(chan bool.1)
go func(ch chan bool, t int) {
time.Sleep(time.Second * time.Duration(t))
ch <- true
}(timeout,2)
select {
case msg:=<-ch1:
fmt.Println("ch1 recvied data",msg)
case ms2:=<-ch2:
fmt.Println("ch2 recvied data",ms2)
case <-timeout:
fmt.Println("Timeout, exit.")}}Copy the code
The output is as follows
Timeout, exit.
Copy the code
6. To sum up
Select is similar to Switch, but it is used in more specific scenarios. Here are a few differences you need to know as you follow this article:
- Select can only be used for channel operations (write/read), whereas switch is more general;
- Select cases are random, whereas switch cases are sequential;
- Select to avoid deadlock, but also can implement their own timeout mechanism;
- There is no use of switch fallthrough in select;
- Select cannot be followed by functions or other expressions like switch.