Go 语言(Golang)中的 select 语句。这是一个在并发编程中非常重要的特性,尤其适合处理多个通道(channel)操作。select 类似于 switch 语句,但专为通道设计,能让 goroutine 等待多个通道的发送或接收操作,并执行第一个准备好的操作。
Go 的并发模型以 goroutine 和 channel 为核心,而 select 是让它们高效协作的“调度员”。它能避免死锁、实现超时控制,还能处理多路复用。
什么是 select 语句?
在 Go 中,select 语句允许一个 goroutine 同时监听多个通道操作(如发送或接收)。它会阻塞,直到至少一个 case 准备好执行;如果多个 case 同时就绪,则随机选择一个。这使得并发代码更简洁,避免了轮询通道的低效。
基本语法
select {
case <-ch1: // 从 ch1 接收(忽略值)
// 处理逻辑
case ch2 <- value: // 向 ch2 发送 value
// 处理逻辑
case x := <-ch3: // 从 ch3 接收并赋值给 x
// 处理逻辑
default: // 如果没有 case 就绪,执行默认分支
// 非阻塞处理
}
- 阻塞行为:无
default时,select会等待,直到某个 case 可执行。 - 随机选择:多 case 就绪时,随机挑选一个(伪随机)。
- 空 select:
select {}会永远阻塞,常用于故意挂起 goroutine。
select 是否执行所有 case?
一个常见问题是:select 会执行所有 case 吗?答案是不会,select 只会执行一个就绪的 case,然后退出 select 块。以下是具体行为:
- 单一执行:
select检查所有 case 的通道状态(发送或接收),只执行第一个就绪的 case,执行后立即退出。 - 随机选择:如果多个 case 同时就绪(例如多个通道有数据或可发送),
select会伪随机选择一个 case。 - 阻塞行为:无
default且无 case 就绪时,select阻塞直到有 case 可用;有default时,若无 case 就绪,立即执行default。 - 循环处理:若需处理多个通道的数据,需将
select放在for循环中,逐次执行。
基本用法示例
让我们通过示例理解 select 的行为。假设有两个通道 ch1 和 ch2,我们用 select 等待其中一个发送消息。
示例 1:监听多个接收通道
package main
import (
"fmt"
"time"
)
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(1 * time.Second)
ch1 <- "消息从 ch1"
}()
go func() {
time.Sleep(2 * time.Second)
ch2 <- "消息从 ch2"
}()
select {
case

最低0.47元/天 解锁文章
677

被折叠的 条评论
为什么被折叠?



