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