它是一个控制结构,可以看成是只用于管道的switch,每个case都必须是管道操作,它将随机选取一个可运行的case,如果,所有都不可运行,则它将阻塞,它具备一下性质
1.每个 case 都必须是一个通信
2.所有 channel 表达式都会被求值
3.所有被发送的表达式都会被求值 // 2和3总结下就是所有入管道的操作,都会先将入管道的值精确地算出来,然后才会去判断它应该执行那个case
4.如果任意某个通信可以进行,它就执行,其他被忽略。
5.如果有多个 case 都可以运行,Select 会随机公平地选出一个执行。其他不会执行。否则:
1)如果有 default 子句,则执行该语句。
2)如果没有 default 子句,select 将阻塞,直到某个通信可以运行;Go 不会重新对 channel 或值进行求值。
6.可处理一个或多个 channel 的发送/接收操作。
7.如果多个 case 同时满足,select 会随机选择一个执行。
8.对于没有 case 的 select 会一直阻塞,可用于阻塞 main 函数,防止退出。(可放在main函数结尾,所有协程执行完了会以死锁的形式退出)
主要用途:
1.一个协程多路复用执行管道操作
2.多个channel全部ready,随机选择一个执行
3.判断管道是否存满,如下图所示
package main
import (
"fmt"
"time"
)
// 判断管道有没有存满
func main() {
// 创建管道
output1 := make(chan string, 10)
// 子协程写数据
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)
}
}