GO_并发编程---select 一、select 基础介绍1. select 与 switch 区别switch匹配相等条件可写任意表达式select每个 case 只能是 channel IO 操作读通道 / 写通道专门用于同时监听多个通道读写状态。2. select 标准语法结构goselect { case -chan1: // 通道chan1可读执行该分支 case chan2 - 100: // 通道chan2可写执行该分支 default: // 所有case都阻塞无就绪IO时立刻执行default非阻塞 }3. 核心执行规则扫描所有 case收集当前就绪的通道 IO 分支若多个 case 同时就绪随机选择其中一个执行无固定顺序若无任何 case 就绪且存在default直接走 default不阻塞若无任何 case 就绪、也无 defaultselect 永久阻塞直到某个通道 IO 就绪。二、实战案例 1select 实现斐波那契数列多通道监听生产 退出信号需求生产者持续向通道写入斐波那契数字消费者读取 8 个数字后发送退出信号生产者收到信号结束协程。gopackage main import fmt // 生产者ch只写quit只读 func fibonacci(ch chan- int, quit -chan bool) { x, y : 1, 1 for { select { case ch - x: // 成功写入数字更新斐波那契 x, y y, xy case flag : -quit: // 收到退出信号结束生产者协程 fmt.Println(flag , flag) return } } } func main() { ch : make(chan int) // 传输斐波那契数字 quit : make(chan bool) // 退出信号通道 // 消费者协程读取8个数字后发送退出信号 go func() { for i : 0; i 8; i { num : -ch fmt.Println(num) } // 读取完成通知生产者退出 quit - true }() // 启动生产者 fibonacci(ch, quit) fmt.Println(程序结束) }流程梳理主协程启动消费者协程fibonacci通过 select 同时监听「写数字通道」和「退出通道」前 8 次ch 可写持续输出 1,1,2,3,5,8,13,21读完 8 个数字后消费者向 quit 发送 trueselect 捕获 quit 通道数据生产者 return 退出函数。三、实战案例 2select 配合 time.After 实现超时控制业务场景监听通道数据若 3 秒内没有数据到达判定为超时主动退出程序。gopackage main import ( fmt time ) func main() { ch : make(chan int) quit : make(chan bool) // 消费协程监听通道超时 go func() { for { select { case num : -ch: fmt.Println(num , num) case -time.After(3 * time.Second): fmt.Println(超时无数据输入) quit - true return } } }() // 主线程持续向通道发送5个数字间隔1秒 for i : 0; i 5; i { ch - i time.Sleep(time.Second) } // 等待超时信号 -quit fmt.Println(程序结束) }运行逻辑主线程每隔 1s 发送数字3 秒超时永远不会触发如果注释掉主线程发送逻辑3 秒后time.After通道就绪进入超时分支程序退出。四、select 关键知识点总结适用场景同时监听多个 channel的读写状态是协程多路复用核心case 限制只能是通道读 / 写操作不能是普通表达式多分支同时就绪随机任选一个执行default 作用让 select 变成非阻塞无就绪通道时直接执行 default超时经典用法case -time.After(时长)无需手动创建 Timer多信号协同可同时监听业务数据通道 退出信号通道优雅关闭协程。