当前位置:网站首页>select statement in go
select statement in go
2022-08-03 09:32:00 【m0_67394230】
在golang语言中,select语句 就是用来监听和channel有关的IO操作,当IO操作发生时,触发相应的case动作.有了 select语句,可以实现 main主线程 与 goroutine线程 之间的互动.
select {
case <-ch1 : // 检测有没有数据可读
// 一旦成功读取到数据,则进行该case处理语句
case ch2 <- 1 : // Have test data can be written
// Once to successch2写入数据,则进行该case处理语句
default:
// 如果以上都没有符合条件,那么进入default处理流程
}
注意事项:
select语句 只能用于channel信道的IO操作,每个case都必须是一个信道.
如果不设置 default条件,当没有IO操作发生时,select语句就会一直阻塞;
如果有一个或多个IO操作发生时,Go运行时会随机选择一个case执行,但此时将无法保证执行顺序;
对于case语句,如果存在信道值为nil的读写操作,则该分支将被忽略,可以理解为相当于从select语句中删除了这个case;
对于空的 select语句,会引起死锁;
对于在 for中的select语句,不能添加 default,否则会引起cpu占用过高的问题;
1.先举个简单例子
First create two channel,并在 select 前往 c2 发送数据
package main
import (
"fmt"
)
//go的通道选择器 让你可以同时等待多个通道操作.go协程和通道以及选择器的结合是go的一个强大特性.
func main() {
// 在我们的例子中,我们将从两个通道中选择.
c1 := make(chan string, 1)
c2 := make(chan string, 1)
c2 <- "nihao"
//go func() {
// time.Sleep(time.Second * 1)
// c1 <- "one"
//}()
//
//go func() {
// time.Sleep(time.Second * 2)
// c2 <- "two"
//}()
//我们使用 `select` 关键字来同时等待这两个值,并打印各自接收到的值.
//for i := 0; i < 2; i++ {
select {
case msg1 := <-c1:
fmt.Println("received", msg1)
case msg2 := <-c2:
fmt.Println("received", msg2)
default:
fmt.Println("No data received")
}
//}
}
在运行 select 时,会遍历所有(如果有机会的话)的 case 表达式,As long as there is a channel has received data,那么 select 就结束,所以输出如下
2. 避免造成死锁
select 在执行过程中,Must hit a branch of them.
If after traversing all of the case 后,若没有命中(命中
:Perhaps this description is not accurate,I meant to say you can perform channel operating statement)任何一个 case 表达式,就会进入 default The code in the branch.
package main
import (
"fmt"
)
//go的通道选择器 让你可以同时等待多个通道操作.go协程和通道以及选择器的结合是go的一个强大特性.
func main() {
// 在我们的例子中,我们将从两个通道中选择.
c1 := make(chan string, 1)
c2 := make(chan string, 1)
//c2 <- "nihao"
//go func() {
// time.Sleep(time.Second * 1)
// c1 <- "one"
//}()
//
//go func() {
// time.Sleep(time.Second * 2)
// c2 <- "two"
//}()
//我们使用 `select` 关键字来同时等待这两个值,并打印各自接收到的值.
//for i := 0; i < 2; i++ {
select {
case msg1 := <-c1:
fmt.Println("received", msg1)
case msg2 := <-c2:
fmt.Println("received", msg2)
//default:
// fmt.Println("No data received")
//}
}
}
But if you didn't write default 分支,select 就会阻塞,直到有某个 case 可以命中,And if there has been no hit,select 就会抛出deadlock
的错误,就像下面这样子.
1.解决这个问题的方法有两种
一个是,养成好习惯,在 select 的时候,也写好 default 分支代码,尽管你 default Didn't write any code.
另一个是,Let one channel can receive data
2. select 随机性
之前学过 switch 的时候,知道了 switch 里的 case 是顺序执行的,但在 select But not in the.
By the following example results can be seen
3. select 的超时
当 case In the channel has not received data,而且也没有 default 语句时,select As a whole will be blocked,But sometimes we do not want to select 一直阻塞下去,This time you can manually set a timeout time.
4. 读取/写入都可以
上面例子里的 case,All seem to only read data from the channel,但实际上,select 里的 case Expression requirements to the operation of the channel you are only can,No matter you are to write data channel,Or read data from a channel.
5. 总结一下
select 与 switch 原理很相似,But its usage scenario is more special,Learning this article,What time do you need to know the following difference:
- select 只能用于 channel 的操作(写入/读出),而 switch 则更通用一些;
- select 的 case 是随机的,而 switch 里的 case 是顺序执行;
- select 要注意避免出现死锁,同时也可以自行实现超时机制;
- select 里没有类似 switch 里的 fallthrough 的用法;
- select 不能像 switch 一样接函数或其他表达式.
先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在.深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小.自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前.因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担.添加下方名片,即可获取全套学习资料哦
边栏推荐
- 深度学习之 10 卷积神经网络2
- Flink Yarn Per Job - 创建启动Dispatcher RM JobManager
- 固件工程师到底是干什么?
- mysqldump导出提示:mysqldump [Warning] Using a password on the command line interface can be insecure
- MYSQL 修改时区的几种方法
- Go的Gin框架学习
- oracle ASM磁盘空间的查看
- 长短期记忆网络 LSTM
- Redis实现分布式锁
- STP普通生成树安全特性— bpduguard特性 + bpdufilter特性 + guard root 特性 III loopguard技术( 详解+配置)
猜你喜欢
随机推荐
Flink Yarn Per Job - 提交应用
Exception: Dataset not found.解决办法
LINGO 18.0软件安装包下载及安装教程
Oracle 迁移至Mysql
LINGO 18.0 software installation package download and installation tutorial
2022最新整理软件测试常见面试题附答案
ORA-06512 数字或值错误字符串缓冲区太小
固件工程师到底是干什么?
文章列表的显示 以及创建文章 还有文章详情的基本
手把手教你如何自制目标检测框架(从理论到实现)
Qt 下拉复选框(MultiSelectComboBox)(一) 实现下拉框多选,搜索下拉框内容
What are pseudo-classes and pseudo-elements?The difference between pseudo-classes and pseudo-elements
Industry SaaS Microservice Stability Guarantee Actual Combat
好用的插件
flutter 应用 抓包
cert-manager使用
SAP Analytics Cloud 和 SAP Cloud for Customer 两款 SaaS 软件的集成
MySQL的主从复制
【快手面试】Word2vect生成的向量,为什么可以计算相似度,相似度有什么意义?
基于百度AI和QT的景物识别系统