This is a creation in Article, where the information may have evolved or changed.
What's wasting today is tomorrow to those who died yesterday; What's the future of hate now?
What you are wasting today is the tomorrow that the man who died yesterday expects, and what you dislike is now the future you will never go back to.
Select Introduction
The SELECT statement is used to choose from multiple Send/Receive channel operations. Select stops blocking until one of the Send/Receive operations is ready. If more than one operation is ready, randomly select one. Syntax is similar to switch, except that each case statement is a channel operation.
Let's go straight into some code to get a better understanding.
package mainimport ("fmt""time")func server1(ch chan string) {time.Sleep(2 * time.Second)ch <- "from server1"}func server2(ch chan string) {time.Sleep(1 * time.Second)ch <- "from server2"}func main() {output1 := make(chan string)output2 := make(chan string)go server1(output1)go server2(output2)select {case s1 := <-output1:fmt.Println(s1)case s2 := <-output2:fmt.Println(s2)}// time.Sleep(4*time.Second)}
Explanation: Main process starts two goroutine to send data to the channel, select is responsible for listening (always in a blocking state), waiting for one of the goroutine to send the data successfully, select immediately stop blocking and receive data after exiting Select.
Imagine: If we open the comment section in the code, does the output of the program change?
Prevent blocking or default
When the case is not ready (fetch to the data), the default statement executes, preventing the blocking state of select from appearing.
package mainimport ("fmt""time")func process(in chan string) {for {time.Sleep(4 * time.Second)in <- "数据写入"}}func main(){in := make(chan string)go process(in)for{time.Sleep(2*time.Second)select{case str := <-in :fmt.Println("接受到数据:",str)default:fmt.Println("等待中...")}}}
When the Mian process starts a goroutine to write data to the channel, the main thread starts for listening in the in channel, and after sleep 2 seconds, the <-in fails to read the data, select prints the data within the default and waits until after the sleep in channel to pass the data.
Dead lock
When no data is sent, only the data is received from the channel, the program will be permanently blocked, resulting in a deadlock.
func main() { ch := make(chan string) select { case <-ch: }}
Select receives data from the nil channel
package mainimport "fmt"func main() {var ch chan stringselect {case v := <-ch:fmt.Println("received value", v)default:fmt.Println("default case executed")}}
Summary: The default statement in select is executed in the defaults to prevent program blocking from being generated.
Random Select
If there are multiple channels in the case statement to send data, how will the select output?
package mainimport ( "fmt" "time")func server1(ch chan string) { ch <- "from server1"}func server2(ch chan string) { ch <- "from server2"}func main() { output1 := make(chan string) output2 := make(chan string) go server1(output1) go server2(output2) time.Sleep(2 * time.Second) // 使所有goroutine的channel写入数据 select { case s1 := <-output1: fmt.Println(s1) case s2 := <-output2: fmt.Println(s2) }}
Select will randomly select the output from, so the output may be different.
Empty Select
As we said above, select does not stop blocking until it receives data in the case (without default).
So what happens to the empty select?
package mainfunc main() { select {}}
The program is permanently blocked (triggers a deadlock).