Go语言select语句示例解析请求:新手学习疑问
Hey there! Let's break down this Go select statement example step by step to help you understand how it works. First, let's fix the incomplete code snippet you provided to make it runnable (the default case was cut off):
package main import "fmt" func main() { var c1, c2, c3 chan int var i1, i2 int select { case i1 = <-c1: fmt.Printf("received %d from c1\n", i1) case c2 <- i2: fmt.Printf("sent %d to c2\n", i2) case i3, ok := (<-c3): // same as: i3, ok := <-c3 if ok { fmt.Printf("received %d from c3\n", i3) } else { fmt.Printf("c3 is closed\n") } default: fmt.Printf("No channel operations are ready to execute!\n") } }
Key Background on select
First, a quick recap: The select statement in Go lets you wait on multiple channel operations at once. It will block until one of the case clauses is ready to execute. If multiple cases are ready, it picks one randomly. If none are ready and there's a default clause, it runs that immediately.
Line-by-Line Breakdown of the Example
Let's go through each part of the select block:
First case:
case i1 = <-c1:- This is a channel receive operation: it tries to pull a value from
c1and assign it toi1. - But here's the catch:
c1is declared withvar c1 chan intbut never initialized (so it'snil). Anilchannel's receive operation will block forever—this case will never be triggered.
- This is a channel receive operation: it tries to pull a value from
Second case:
case c2 <- i2:- This is a channel send operation: it tries to send the value of
i2(which is0, since it's an uninitializedint) toc2. - Again,
c2isnil. Sending to anilchannel also blocks forever, so this case won't run either.
- This is a channel send operation: it tries to send the value of
Third case:
case i3, ok := (<-c3):- This is a receive operation with an
okflag, which lets us check if the channel is closed. - Once more,
c3isnil. Receiving from anilchannel blocks forever, so this case can't execute. Even ifc3were closed later, since it'snilright now, this code path is unreachable in this example.
- This is a receive operation with an
Default case
- Since all three channel operations are blocked (thanks to the
nilchannels), theselectfalls back to thedefaultclause immediately. It will printNo channel operations are ready to execute!when you run the code.
- Since all three channel operations are blocked (thanks to the
What This Example Teaches You
This is a great demonstration of what happens when you use select with uninitialized (nil) channels: all send/receive operations on nil channels block indefinitely, so if you have a default clause, that's the only code that will run.
A few extra notes to remember:
- If there was no
defaultclause here, theselectwould block forever, because none of the channel operations can complete. - When multiple non-blocking cases are ready,
selectpicks one at random to prevent starvation (no single case gets prioritized over others). - The
okflag in receive operations is useful: when a channel is closed and has no more values to read,okwill befalse, letting you handle closed channels gracefully.
内容的提问来源于stack exchange,提问作者Andy Hermann

