语法具体定义参考官方定义
https://golang.org/ref/spec#Select_statements
select
语句执行分以下一个步骤执行
- 所有channel表达式都会被求值、所有被发送的表达式都会被求值。求值顺序:自上而下、从左到右。
- 如果有一个或多个通信操作可以完成,则Go运行时系统会伪随机的选择一个执行。否则,如果有default分支,则执行default分支语句,如果连default都没有,则select语句会一直阻塞,直到至少有一个通信操作可以进行。
案例分析
所有channel表达式都会被求值、所有被发送的表达式都会被求值。求值顺序:自上而下、从左到右
func main() {
var ch1 chan int
var ch2 chan int
var chs = []chan int{ch1, ch2}
var numbers = []int{1, 2, 3, 4, 5}
getNumber := func(i int) int {
fmt.Printf("numbers[%d]\n", i)
return numbers[i]
}
getChan := func(i int) chan int {
fmt.Printf("chs[%d]\n", i)
return chs[i]
}
select {
case getChan(0) <- getNumber(2):
fmt.Println("1th case is selected.")
case getChan(1) <- getNumber(3):
fmt.Println("2th case is selected.")
default:
fmt.Println("default case")
}
}
输出:
chs[0]
numbers[2]
chs[1]
numbers[3]
default case
Process finished with exit code 0
如果有一个或多个通信操作可以完成,则Go运行时系统会伪随机的选择一个执行。否则,如果有default分支,则执行default分支语句,如果连default都没有,则select语句会一直阻塞,直到至少有一个通信操作可以进行
- 所有case语句都被阻塞时,如果有default语句,执行default语句
func main() {
start := time.Now()
ch1 := make(chan int)
ch2 := make(chan int)
go func() {
time.Sleep(2 * time.Second)
ch1 <- 3
}()
go func() {
time.Sleep(3 * time.Second)
ch2 <- 5
}()
fmt.Println("blocking on read...")
select {
case <-ch1:
fmt.Printf("ch1 case...")
case <-ch2:
fmt.Printf("ch2 case...")
default:
fmt.Printf("default case...")
}
}
输出:
blocking on read...
default case...
Process finished with exit code 0
- 所有case语句都被阻塞时,当没有default语句时,select阻塞等待
func main() {
start := time.Now()
ch1 := make(chan int)
ch2 := make(chan int)
go func() {
time.Sleep(2 * time.Second)
ch1 <- 3
}()
go func() {
time.Sleep(3 * time.Second)
ch2 <- 5
}()
fmt.Println("blocking on read...")
select {
case <-ch1:
fmt.Printf("ch1 case...")
case <-ch2:
fmt.Printf("ch2 case...")
}
}
输出:
blocking on read...
ch1 case...
Process finished with exit code 0
- 当多个case语句都可以被执行时,伪随机的选择一个执行
func main() {
start := time.Now()
ch1 := make(chan int)
ch2 := make(chan int)
go func() {
time.Sleep(1 * time.Second)
ch1 <- 3
}()
go func() {
time.Sleep(1 * time.Second)
ch2 <- 5
}()
fmt.Println("blocking on read...")
select {
case <-ch1:
fmt.Printf("ch1 case...")
case <-ch2:
fmt.Printf("ch2 case...")
}
}
输出:
blocking on read...
ch1 case...
Process finished with exit code 0
blocking on read...
ch2 case...
Process finished with exit code 0
有疑问加站长微信联系(非本文作者)