What is select?
select
Yes used in GoMulti-channel operationThe control structure of , which can listen to the sending and receiving operations of multiple channels,Execute the corresponding statement when one of them can be performed, thereby realizing non-blocking concurrent communication.
Basic syntax
select { case val := <-ch1: // Execute when ch1 is readablecase ch2 <- 100: // ch2 is executed when it is writabledefault: // Execute when all channels are blocked (optional)}
Each
case
Must beSend (ch <- val) or receive (val := <-ch)Only one actionable
case
(If there are multiple ones, you can choose one at random)If all block, and no
default
,select
Will block and waitIf included
default
, it will execute immediately, even if it is othercase
It is possible to operate afterwards
Examples of usage scenarios
1. Listen to data from multiple channels
select { case msg1 := <-ch1: ("Received ch1:", msg1) case msg2 := <-ch2: ("Received ch2:", msg2) }
2. Implement the timeout mechanism
select { case msg := <-ch: ("receive:", msg) case <-(2 * ): ("time out") }
Returns a channel that becomes readable after a specified time, achieving elegant timeout.
3. Non-blocking sending or receiving (default branch)
select { case ch <- data: ("Send successfully") default: ("channel full, give up sending") }
4. Check whether the channel is closed
select { case v, ok := <-ch: if !ok { ("Channel Close") } else { ("receive:", v) } }
The behavioral characteristics of select
Behavior | describe |
---|---|
Random Scheduling | Randomly select one execution when multiple cases are available at the same time (prevent hunger) |
Blocking and waiting | When all cases block, select itself blocks |
default branch | All cases are blocked immediately to avoid blocking |
Choose only one | Only one of them is executed when multiple are satisfied at the same time |
Work with goroutine: Producer/Consumer Model
func producer(ch chan int) { for i := 0; i < 5; i++ { ch <- i } close(ch) } func consumer(ch chan int, done chan struct{}) { for { select { case val, ok := <-ch: if !ok { done <- struct{}{} return } ("Consumption:", val) } } }
select + for: Common loop writing methods
for { select { case msg := <-ch: ("receive:", msg) case <-(5 * ): ("Timeout Exit") return } }
select Common traps
trap | describe |
---|---|
Forgot default causes blockage | If all cases block, select also blocks |
Infinite blockage | All channels in select will never be available |
channel closed | Write panic to closed channels, be careful |
Timeout misuse | When using (),Don't create new channels frequently in loops, otherwise the memory leaks |
🔍 Solve Suggestions:useand multiplex the timer.
Practical advice
suggestion | reason |
---|---|
Use select to implement timeout control | More elegant and non-blocking |
select + default implements non-blocking communication | Avoid goroutine stuck |
Use select + () to control exit | More suitable for large systems |
Example: context control exit (recommended production use)
ctx, cancel := ((), 3*) defer cancel() ch := make(chan int) go func() { (2 * ) ch <- 42 }() select { case <-(): ("Operation Cancel/Timeout:", ()) case val := <-ch: ("Received data:", val) }
Summarize
Dimension | illustrate |
---|---|
Function | Implement multiplexed listening for channel |
advantage | Non-blocking, efficient and elegant communication control |
Combined | , context, default The best combination |
Scene | goroutine exit, task timeout, concurrent inter-coroutine communication control, etc. |
This is the end of this article about select in Go language. For more detailed explanations of Go select, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!