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) } }

    推荐阅读