看了两篇博客,一个说:在任何一个 case 中执行 break 或者 return,select 就结束了。
另一个说:break只能跳出select中的一个case
验证了一下,不知道对不对,感觉是跳出了整个select
func main() {
v := make(chan int)
o := make(chan bool)
select {
case d := <-v:
fmt.Println("ddd", d)
case <-time.After(time.Second * 5):
fmt.Println("timeout")
//o <- true
break
}
fmt.Println("ssssssssssssss")
time.Sleep(time.Second * 100)
<-o
fmt.Println("程序结束")
}
package main
import (
"fmt"
"time"
)
/*
1.监听的case中,没有满足条件的就阻塞
2.多个满足的条件就任选一个执行
3.select本身不带循环,需要外层的for循环
4.default通常不用,会产生忙轮训
5.break只能跳出select中的一个case
1.加入了默认分支,那么无论涉及通道操作的表达式是否有阻塞,select语句都不会被阻塞。如果那几个表达式都阻塞了,或者说都没有满足求值的条件,那么默认分支就会被选中并执行。
2.如果没有加入默认分支,那么一旦所有的case表达式都没有满足求值条件,那么select语句就会被阻塞。直到至少有一个case表达式满足条件为止。
如果select语句发现同时有多个候选分支满足选择条件,那么它就会用一种伪随机的算法在这些分支中选择一个并执行。注意,即使select语句是在被唤醒时发现的这种情况,也会这样做
*/
/*
go里面提供了一个关键字select,通过select可以监听channel上的数据流动
select的用法与switch语言非常类似,由select开始一个新的选择块,每个选择块条件由case语句来描述
与switch语句可以选择任何可使用相等比较的条件相比,select有比较多的限制,其中最大的一条限制就是每个case语句里必须是一个IO操作
for{
select {
case <- chan1:
//
case <- chan2:
//
default:
//case表达式都没有满足求值条件,
}
}
*/
/*
在一个select语句中,go语言会按顺序从头到尾评估每一个发送和接收的语句
如果其中的任意一语句可以继续执行(即没有被阻塞),那么就从哪些可以执行的语句中任意选择一条来使用
如果没有任意一条语句可以执行(即所有的通道都被阻塞),那么有两种可能的情况:
如果给出了default语句,那么就会执行default语句,同时程序的执行会从select语句后的语句中恢复
如果没有default语句,那么select语句将被阻塞,直到至少有一个通信可以进行下去
*/
/*
防止channel超时机制
有时候会出现协程阻塞的情况,那么我们如何避免这个情况?我们可以使用select来设置超时
*/
//func main() {
// v := make(chan int)
// o := make(chan bool)
//
// select {
// case d := <-v:
// fmt.Println("ddd", d)
// case <-time.After(time.Second * 5):
// fmt.Println("timeout")
// //o <- true
// break
// }
// fmt.Println("ssssssssssssss")
//
// time.Sleep(time.Second * 100)
// <-o
//
// fmt.Println("程序结束")
//}
//超时这种写法也常常用来设置定时执行某段函数
//go func() {
// select {
// case <- time.After(5 * time.Second):
// dosomething()
// }
//}
/*
default 语句是可选的;fallthrough 行为,和普通的 switch 相似,是不允许的。在任何一个 case 中执行 break 或者 return,select 就结束了。
select 做的就是:选择处理列出的多个通信情况中的一个。
如果都阻塞了,会等待直到其中一个可以处理
如果多个可以处理,随机选择一个
如果没有通道操作可以处理并且写了default 语句,它就会执行:default 永远是可运行的(这就是准备好了,可以执行)。
在 select 中使用发送操作并且有 default 可以确保发送不被阻塞!如果没有 default,select 就会一直阻塞。
select 语句实现了一种监听模式,通常用在(无限)循环中;在某种情况下,通过 break 语句使循环退出。
*/
func main() {
ch1 := make(chan int)
ch2 := make(chan int)
go pump1(ch1)
go pump2(ch2)
go suck(ch1, ch2)
time.Sleep(1e9)
}
func pump1(ch chan int) {
for i := 0; ; i++ {
ch <- i * 2
}
}
func pump2(ch chan int) {
for i := 0; ; i++ {
ch <- i + 5
}
}
func suck(ch1, ch2 chan int) {
for {
select {
case v := <-ch1:
fmt.Printf("Received on channel 1: %d\n", v)
case u := <-ch2:
fmt.Printf("Received on channel 2: %d\n", u)
}
}
}
/*
在程序 goroutine_select.go 中有 2 个通道 ch1 和 ch2,三个协程 pump1()、pump2() 和 suck()。
这是一个典型的生产者消费者模式。
在无限循环中,ch1 和 ch2 通过 pump1() 和 pump2() 填充整数;
suck() 也是在无限循环中轮询输入的,
通过 select 语句获取 ch1 和 ch2 的整数并输出。
选择哪一个 case 取决于哪一个通道收到了信息。程序在 main 执行 1 秒后结束。
-----------------------------------
©著作权归作者所有:来自51CTO博客作者宇宙之一粟的原创作品,请联系作者获取转载授权,否则将追究法律责任
Go 语言入门很简单:使用 select 切换协程
https://blog.51cto.com/yuzhou1su/5416579
*/
标签:case,语句,协程,一抄,阻塞,break,表达式,Go,select
From: https://www.cnblogs.com/jianjiana/p/16975651.html