Go中select行为规则和执行顺序的实现
作者:Kevin666
Go语言中的select语句用于在多个通信操作中进行选择,本文就来详细的介绍一下Go中select行为规则和执行顺序的实现,具有一定的参考价值,感兴趣的可以了解一下
Go 语言中 select 语句的行为规则和执行顺序。
✅ 规则1:每个case表达式必须有发送或接收操作,可能还有其他表达式
含义:
每个 case 至少要有一个通道操作(<-chan 或 chan<-),可以搭配赋值、函数调用等。
示例:
ch := make(chan int, 1)
select {
case x := <-ch: // 接收操作 + 赋值
fmt.Println("Received:", x)
}
select {
case ch <- computeValue(): // 发送操作 + 函数调用
fmt.Println("Sent")
}
✅ 规则2:表达式求值顺序是从上到下,从左到右
含义:
所有 case 分支中的表达式,在 select 执行之初就按书写顺序全部求值。表达式多于一个时,按从左到右顺序求值。
示例:
ch1 := make(chan int)
ch2 := make(chan int)
select {
case x := <-ch1:
fmt.Println("ch1", x)
case y := <-ch2:
fmt.Println("ch2", y)
}
上面例子中:
- ch1 的接收表达式会先被求值;
- 然后 ch2;
- 然后再看哪个能成功进行选择。
✅ 规则3:如果通道操作阻塞,case 就不满足条件
含义:
当某个 case 执行通道操作时,如果它会阻塞(比如通道没数据,或者通道满) ,它就不能被选中。
示例:
ch := make(chan int)
select {
case ch <- 1: // 没有接收方,发送会阻塞
fmt.Println("sent")
default:
fmt.Println("default")
}
输出:
default
✅ 规则4:只有所有 case 表达式求值完后,select 才选分支
含义:
select 要先静态地评估所有分支是否能执行,然后才在满足条件的分支中挑选一个。
示例:
ch := make(chan int, 1)
ch <- 42
select {
case x := <-ch: // 可执行
fmt.Println("got", x)
case y := <-ch: // 不可执行(通道空了)
fmt.Println("got", y)
}
输出:
got 42
✅ 规则5:多个可选分支时,select 随机选一个
含义:
多个分支都可执行时,select 不会按照书写顺序选第一个,而是随机选一个。
示例:
ch1 := make(chan int, 1)
ch2 := make(chan int, 1)
ch1 <- 1
ch2 <- 2
select {
case x := <-ch1:
fmt.Println("ch1", x)
case y := <-ch2:
fmt.Println("ch2", y)
}
输出可能是:
ch1 1
或者
ch2 2
✅ 规则6:default分支最多只能有一个,并且只在无其他可选时执行
含义:
- default 分支不能有多个;
- 它只有在所有 case 都阻塞时才会被执行;
- 不管你把它写在最上面还是最下面,它只有在“无可选分支”时才会被选中。
示例:
ch := make(chan int)
select {
default:
fmt.Println("default executed")
case <-ch:
fmt.Println("received")
}
输出:
default executed
小结
| 场景描述 | 是否满足选择条件 |
|---|---|
| 通道有数据可读(接收操作) | ✅ |
| 通道有空位可写(发送操作) | ✅ |
| 通道阻塞(接收或发送都不能继续) | ❌ |
| 所有 case 都阻塞 + 有 default | 选中 default |
| 所有 case 都阻塞 + 无 default | select 阻塞 |
| 多个 case 都满足条件 | 随机选一个 |
到此这篇关于Go中select行为规则和执行顺序的实现的文章就介绍到这了,更多相关Go select行为规则和执行顺序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
