select:多路复用机制,用于监听多个管道,当我们不知道该怎么去处理channel的关闭时,可使用select
注意:select里的case执行是无序的
用法
select { //不停的在这里检测
case <-chanl : //检测有没有数据可以读
//如果chanl成功读取到数据,则进行该case处理语句,处理完退出select
case chan2 <- 1 : //检测有没有可以写
//如果成功向chan2写入数据,则进行该case处理语句,处理完退出select
//假如没有default,那么在以上两个条件都不成立的情况下,就会在此阻塞
//一般default会不写在里面,select中的default子句总是可运行的,因为会很消耗CPU资源
default:
//如果以上都没有符合条件,那么则进行default处理流程,处理完退出select
}
实例
func main() {
intchan :=make(chan int,10)
primechan :=make(chan int,10)
for i:=0;i<10;i++{
intchan <- i
primechan <- i*2
}
label:
for {
select {
case a:=<-intchan:
fmt.Println("intchan----",a)
case b:=<-primechan:
fmt.Println("primechan---",b)
default:
break label
}
}
}
斐波那契数列
//ch只写,quit只读
func fbn(ch chan<- int, quit <-chan bool) {
x, y := 1, 1
for {
//监听channel数据的流动
select {
case ch <- x: //往里写 。第一次写的时候是1,如果没有地方读的话,那么这里会阻塞
x, y = y, x+y //第一次是往ch写1,y的值也是1,下一次y的值就是x+y
case <-quit:
return
}
}
}
func main() {
ch := make(chan int) //数字通道
quit := make(chan bool) //程序是否结束
go func() {
for i := 0; i < 8; i++ {
num := <-ch //这里读是因为防止select那里会阻塞
fmt.Println(num)
}
quit <- true
}()
fbn(ch, quit)
}
timeout 机制
func main() {
ch := make (chan int)
select {
case <-ch:
case <-time.After(time.Second * 1): //一般不会用time.After
fmt.Println("超时啦!")
}
}
判断channel是否阻塞
func main() {
ch := make (chan int,1) // 注意这里给的容量是1
ch <- 1
select {
case ch <- 2:
default:
fmt.Println("通道channel已经满啦,塞不下东西了!")
}
}