1. select 多路复用
1.1. select说明
- 传统的方法在遍历管道时,如果不关闭会阻塞而导致 deadlock,在实际开发中,可能我们不好确定什么关闭该管道。
- 这种方式虽然可以实现从多个管道接收值的需求,但是运行性能会差很多。
- 为了应对这种场景,Go 内置了 select 关键字,可以同时响应多个管道的操作。
- select 的使用类似于 switch 语句,它有一系列 case 分支和一个默认的分支。
- 每个 case 会对应一个管道的通信(接收或发送)过程。
- select 会一直等待,直到某个 case 的通信操作完成时,就会执行 case 分支对应的语句。
- 具体格式如下:
select {
case <-chan1:
case chan2 <- 1:
default:
}
1.2. select 的使用
- 使用 select 语句能提高代码的可读性。
- 可处理一个或多个 channel 的发送/接收操作。
- 如果多个 case 同时满足,select 会随机选择一个。
- 对于没有 case 的 select{}会一直等待,可用于阻塞 main 函数。
package main
import (
"fmt"
"time"
)
func main() {
intChan := make(chan int, 10)
for i := 0; i < 10; i++ {
intChan <- i
}
stringChan := make(chan string, 5)
for i := 0; i < 5; i++ {
stringChan <- "hello" + fmt.Sprintf("%d", i)
}
for {
select {
case v := <-intChan:
fmt.Printf("从 intChan 读取的数据%d \n", v)
time.Sleep(time.Millisecond * 50)
case v := <-stringChan:
fmt.Printf("从 stringChan 读取的数据%s \n", v)
time.Sleep(time.Millisecond * 50)
default:
fmt.Println("数据获取完毕")
return
}
}
}