Select多路复用
在某些场景下我们需要同时从多个通道接收数据。通道在接收数据时,如果没有数据可以接收将会发生阻塞,而select就可以同时监听一个或多个channel,直到其中一个channel准备好。
select的使用类似于switch语句,它有一系列case分支和一个默认的分支。每个case会对应一个通道的通信(接收或发送)过程。select会一直等待,直到某个case的通信操作完成时,就会执行case分支对应的语句。具体格式如下:
select {
case <-chan1:
// 如果chan1成功读到数据,则进行该case处理语句
case chan2 <- 1:
// 如果成功向chan2写入数据,则进行该case处理语句
default:
// 如果上面都没有成功,则进入default处理流程
}
package mainimport (
"fmt"
"time"
)func test1(ch chan string) {
time.Sleep(time.Second * 1)
ch <- "test1"
}
func test2(ch chan string) {
time.Sleep(time.Second * 2)
ch <- "test2"
}func main() {
// 2个管道
output1 := make(chan string)
output2 := make(chan string)
// 跑2个子协程,写数据
go test1(output1)
go test2(output2)
for {
// 用select监控
select {
case s1 := <-output1:
fmt.Println("s1=", s1)
case s2 := <-output2:
fmt.Println("s2=", s2)
default:
ticker := time.NewTicker(1 * time.Second)
fmt.Printf("%v\n", <-ticker.C)
}
}
}
【Select多路复用】判断通道是否已经存满
package mainimport (
"fmt"
"time"
)// 判断管道有没有存满
func main() {
// 创建管道
output1 := make(chan string, 1)
// 子协程写数据
go write(output1)
// 取数据
for s := range output1 {
fmt.Println("res:", s)
time.Sleep(time.Second)
}
}func write(ch chan string) {
for {
select {
// 写数据
case ch <- "hello":
fmt.Println("write hello")
default:
fmt.Println("channel full")
}
time.Sleep(time.Millisecond * 500)
}
}
推荐阅读
- Apache多路复用模块(MPMs)介绍
- Spring|Spring Boot之ImportSelector
- performSelectorOnMainThread:withObject:waitUntilDone:参数设置为NO或YES的区别
- 没有复用的cell|没有复用的cell 单元格的写法
- select|select bell
- 流浪爱情(16.5)
- 算法笔记(1)|算法笔记(1)| 排序
- select函数socket编程
- MySQL学习笔记-9-order by
- Go|Go Quiz: 从Go面试题看channel在select场景下的注意事项