In golang language, the select statement is used to listen for IO operations related to channel. When the IO operation occurs, the corresponding case action is triggered.
With the select statement, the interaction between the main thread and the goroutine thread can be realized.
1. Basic syntax
select { case <-ch1 : // Check whether there is any data to read // Once the data is successfully read, the case processing statement is performed case ch2 <- 1 : // Check if there is any data to write // Once the data is successfully written to ch2, the case processing statement is performed default: // If none of the above meets the conditions, then enter the default processing process}
Things to note
- The select statement can only be used for IO operations on the channel channel, and each case must be one channel.
- If the default condition is not set, the select statement will keep blocking when no IO operation occurs;
- If one or more IO operations occur, the Go runtime will randomly select a case to execute, but the execution order will not be guaranteed at this time;
- For a case statement, if there is a read and write operation with a channel value of nil, the branch will be ignored, which can be understood as equivalent to deleting this case from the select statement;
- For empty select statements, a deadlock will be caused;
- For the select statement in for, you cannot add default, otherwise it will cause the problem of excessive CPU usage;
(1) When multiple IO operations occur, the case statement is executed randomly
func main() { ch1 := make(chan int, 1) // Create an integer channel with buffered length ch1 <- 1 // Write data into the channel ch2 := make(chan int, 1) ch2 <- 2 select { case <- ch1: ("ch1 read") case <- ch2: ("ch2 read") } }
After multiple executions, "ch1 read" or "ch2 read" will be randomly printed
(2) Empty select statement
func main() { select { } }
After execution, a deadlock is raised and the printing is as follows:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [select (no cases)]:
()
xxx/:4 +0x27
exit status 2
(3) Select in for causes excessive CPU resource consumption
func main() { quit := make(chan bool) go func() { for { select { case <-quit: ("quit") // Use return to exit the entire goroutine thread; if you use break, the program will still be executed in the for loop return default: ("default") } } }() (3 * ) quit <- true // The main thread writes data to the quit channel after 3 seconds (2 * ) ("main") }
After using default in the select statement of for{}, the thread will execute the default condition infinitely until the data is read in the quit channel, otherwise it will run in a dead loop, resulting in the entire CPU resource being filled.
In the select statement of for{}, it is not recommended to use the default condition.
The practical application of statements
(1) Implement interaction and communication between the main thread and the goroutine thread
// Enter "bye" on the console to control the end of the main functionfunc main() { quit := make(chan bool) ch := make(chan string) go func() { for { select { case name := <-ch: ("from main msg: [%v]\n", name) if name == "bye" { quit <- true } else { quit <- false } } } }() for { //Console input ("please input string: ") scanner := () () ch <- () isOver := <- quit if isOver { break } } ("main over") }
run:
from main msg: [aaa]
please input string: bbb
from main msg: [bbb]
please input string: bye
from main msg: [bye]
main over
(2) Timeout implementation
func main() { quit := make(chan bool) ch := make(chan int) go func() { for { select { case num := <- ch: ("num = ", num) case <- (5 * ): ("time out") quit <- true } } }() for i := 0; i < 2; i++ { ch <- i () } <- quit // After waiting for the timeout, end the main thread ("Program End") }
This is the end of this article about how to use select in Go language. For more relevant content on select, please search for my previous articles or continue browsing the following related articles. I hope you support me in the future!