This article reviews some of the uses of the select
statement in the Go
language and extends a tip on how to implement priority in select
, which I hope will be helpful to you.
Introduction to the select statement
The select
statement in Go is used to monitor and select a set of case
statements to execute the corresponding code. It looks similar to the switch
statement, but all the expressions in the case
in the select
statement must be send or receive operations of the channel
. An example of a typical use of select
is as follows.
The select
keyword in the go language also allows the current goroutine
to wait for ch1
to become readable and ch2
to become writable at the same time, and until the state of ch1
and ch2
changes, select
will block until one of the channels
becomes ready and the corresponding case
branch. If more than one channel
is ready at the same time, then a case
is randomly selected for execution.
In addition to the typical examples shown above, we will introduce some special examples of select
one by one.
Empty select
An empty select means that it does not contain any case inside, e.g.
An empty select statement will directly block the current goroutine, causing it to go into a permanently dormant state where it cannot be woken up.
Only one case
If select
contains only one case
, then the select
becomes a blocking channel
read/write operation.
In the above code, the print operation is executed when ch1
is readable, otherwise it blocks.
With default statement
If select
can also contain a default
statement, it can be used to perform some default operation when none of the other case
s are satisfied.
In the above code, the print operation is executed when ch1
is readable, otherwise the code in the default
statement is executed, which is equivalent to doing a non-blocking channel
read operation.
Summary
- select No case exists: permanently blocks the current goroutine
- select Only one case exists: blocking send/receive
- select exists more than one case: randomly select a case that satisfies the condition and execute it
- select exists default and no other case is satisfied: execute the code in the default statement
Implementing priority in select
It is known that when there are multiple cases in select, one case satisfying the condition is randomly selected for execution.
Now we have a requirement: we have a function that will continuously receive task 1 and task 2 from ch1 and ch2 respectively without interruption.
How can we ensure that when ch1 and ch2 reach the ready state at the same time, task 1 will be executed first, and task 2 will be executed when there is no task 1?
Advanced Go programmer Ming scratched his head and wrote the following function.
The above code implements “priority” by nesting two selects, which seems to meet the requirements of the question. But there is something wrong with this code, if both ch1 and ch2 do not reach the ready state, the whole program will not block but enter a dead loop.
What can we do?
Xiao Ming scratched his head again and wrote down another solution.
|
|
This time, Ming not only uses nested select
, but also a combination of for
loops and LABEL
to achieve the requirements of the question. The above code executes job2 := <-ch2
when the outer select
is selected, and then goes to the inner select
loop to continue trying to execute job1 := <-ch1
, which will keep executing when ch1
is ready, otherwise it jumps out of the inner select
.
Practical application scenarios
Although the above requirements are compiled by me, but about the implementation of priority in select
in the actual production is a practical application of the scene, such as K8s
controller
in the actual use of the above skills examples, here in the select to achieve priority-related code in the key have added comments, the specific logic here will not expand on the details.
|
|
Summary
This article reviews some of the uses of the select statement in Go, and extends a tip on how to implement priority in select, which I hope will be helpful to you.
One last word, Go language doesn’t have a lot of weird syntax sugar and self-contained code formatting compared to other languages, so it doesn’t have the situation of not being able to read the code written by others. So we can totally read the source code of the best libraries, be with giants, be with high friends, and eventually eat better meals.
Reference https://www.liwenzhou.com/posts/Go/priority_in_go_select/