AI写作智能体 自主规划任务,支持联网查询和网页读取,多模态高效创作各类分析报告、商业计划、营销方案、教学内容等。 广告
## 多路复用 Linux本身有个select的多路复用的模型,golang的多路复用使用select关键字的原因可能就是来源于这里吧. 1. 在select没有case的情况下,它会阻塞当前的goroutine. 2. 每一个case都必须是一个channel通信. 3. select的执行跟**case的顺序没有关系**.哪个case有通信活动了,就去执行哪一个. 4. 当一个case可以被执行的时候,其他的所有case将会被忽略,程序代码将继续向下执行.跳过所有被忽略的case. 5. 如果没有一个case可以被执行,则去执行default. 6. 如果没有default,select将会阻塞,直到有case可以被执行. 7. 多个case同时就绪时,select会随机的选择一个去执行,这样保证每一个channel都有平等的被select的机会. ## 例1 可以看到,虽然timer2在timer1的下面,但是因为timer2早于timer1有通信活动,所以直接执行了timer2,并且timer2执行之后,直接跳出了select,并且忽略了timer1. ~~~ timer1 := time.NewTimer(2 * time.Second) timer2 := time.NewTimer(time.Second) select { case <-timer1.C: fmt.Println("timer1") case <-timer2.C: fmt.Println("timer2") } fmt.Println("done") ~~~ 结果: ``` timer2 done ``` ## 例2 因为timer1和timer2都需要等待,而此时的select是有default的,所以直接执行default,执行后跳出select. ~~~ timer1 := time.NewTimer(2 * time.Second) timer2 := time.NewTimer(time.Second) select { case <-timer1.C: fmt.Println("timer1") case <-timer2.C: fmt.Println("timer2") default: fmt.Println("default") } fmt.Println("done") ~~~ 结果: ``` default done ``` ## 例3 ~~~ abort := make(chan struct{}) go func() { os.Stdin.Read(make([]byte, 1)) abort <- struct{}{} }() tick := time.NewTicker(time.Second) defer tick.Stop() for i := 10; i > 0; i-- { select { case <-tick.C: fmt.Println(i) case <-abort: return } } fmt.Println("launch") ~~~