在一些出现goroutine阻塞的情况下,如何避免整个程序进入阻塞的情况呢?可以采用select来设置超时,具体情况参照下面例子。
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan int)
quit := make(chan bool)
go func() { //子go 程获取数据
for {
select {
case num := <- ch:
fmt.Println("num = ",num)
case <- time.After(3*time.Second):
quit <- true
goto lable
//return 退出func(),如果用break只会跳出当前case
//runtime.Goexit() 结束这个goroutine
}
}
lable: //lable可以在func()内任意位置,但不可在函数之外
fmt.Println("break to label ---")
}()
for i := 0; i < 2; i++ {
ch <- i
time.Sleep(2*time.Second) //每隔2秒向ch写入数据
}
<- quit //主go程阻塞等待子go程通知,退出
fmt.Println("finish !!!")
}
程序输出结果:
num = 0
num = 1
break to label ---
finish !!!
select知识点总结:
- 作用:用来监听channel上的数据流动方向,可以是写也可以是读。
- 用法:参考switch case语法,但case后面必须为IO操作。
注意:
- 监听case中,没有满足监听条件则阻塞
- 监听case中,有多个满足监听条件,任选一个执行
- 可以使用default来处理所有case都不满足监听的条件。
- select自身不带有循环机制,需要借助外层for来循环监听
- break跳出select中的一个case选项,类似于switch中的用法