go中select语句

在golang语言中,select语句 就是用来监听和channel有关的IO操作,当IO操作发生时,触发相应的case动作。有了 select语句,可以实现 main主线程 与 goroutine线程 之间的互动。

select {case <-ch1 :     // 检测有没有数据可读// 一旦成功读取到数据,则进行该case处理语句case ch2 <- 1 :  // 检测有没有数据可写// 一旦成功向ch2写入数据,则进行该case处理语句default:// 如果以上都没有符合条件,那么进入default处理流程
}

注意事项:

select语句 只能用于channel信道的IO操作,每个case都必须是一个信道。
如果不设置 default条件,当没有IO操作发生时,select语句就会一直阻塞;
如果有一个或多个IO操作发生时,Go运行时会随机选择一个case执行,但此时将无法保证执行顺序;
对于case语句,如果存在信道值为nil的读写操作,则该分支将被忽略,可以理解为相当于从select语句中删除了这个case;
对于空的 select语句,会引起死锁;
对于在 for中的select语句,不能添加 default,否则会引起cpu占用过高的问题;

1.先举个简单例子

先创建两个信道,并在 select 前往 c2 发送数据

package mainimport ("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 表达式,只要有一个信道有接收到数据,那么 select 就结束,所以输出如下

2. 避免造成死锁

select 在执行过程中,必须命中其中的某一分支。

如果在遍历完所有的 case 后,若没有命中(命中:也许这样描述不太准确,我本意是想说可以执行信道的操作语句)任何一个 case 表达式,就会进入 default 里的代码分支。

package mainimport ("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")//}}
}

 但如果你没有写 default 分支,select 就会阻塞,直到有某个 case 可以命中,而如果一直没有命中,select 就会抛出 deadlock 的错误,就像下面这样子。

1.解决这个问题的方法有两种

一个是,养成好习惯,在 select 的时候,也写好 default 分支代码,尽管你 default 下没有写任何代码。

 另一个是,让其中某一个信道可以接收到数据

 

2. select 随机性

之前学过 switch 的时候,知道了 switch 里的 case 是顺序执行的,但在 select 里却不是。

通过下面这个例子的执行结果就可以看出

 

3. select 的超时

当 case 里的信道始终没有接收到数据时,而且也没有 default 语句时,select 整体就会阻塞,但是有时我们并不希望 select 一直阻塞下去,这时候就可以手动设置一个超时时间。

4. 读取/写入都可以

上面例子里的 case,好像都只从信道中读取数据,但实际上,select 里的 case 表达式只要求你是对信道的操作即可,不管你是往信道写入数据,还是从信道读出数据。

5. 总结一下

select 与 switch 原理很相似,但它的使用场景更特殊,学习了本篇文章,你需要知道如下几点区别:

  1. select 只能用于 channel 的操作(写入/读出),而 switch 则更通用一些;
  2. select 的 case 是随机的,而 switch 里的 case 是顺序执行;
  3. select 要注意避免出现死锁,同时也可以自行实现超时机制;
  4. select 里没有类似 switch 里的 fallthrough 的用法;
  5. select 不能像 switch 一样接函数或其他表达式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/1620342.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

SQL SELECT语句

SQL语句是由简单地英语单词构成的。这些单词称为关键字&#xff0c;每个SQL语句都是由一个或多个关键字构成的。最经常使用的SQL语句大概就是SELECT语句了&#xff0c;它的用途是从一个或多个表中检索信息 SELECT 语句用于从数据中选取数据。 结果被存储在一个结果表中&#…

权限提升-手工-系统权限提升

权限提升基础信息 1、具体有哪些权限需要我们了解掌握的&#xff1f; 后台权限&#xff0c;网站权限&#xff0c;数据库权限&#xff0c;接口权限&#xff0c;系统权限&#xff0c;域控权限等 2、以上常见权限获取方法简要归类说明&#xff1f; 后台权限&#xff1a;SQL注入,数…

5 群起集群

1.在启动集群之前&#xff0c;先配置workers,有几个节点就配置几个 [atguiguhadoop102 hadoop]$ vim /opt/module/hadoop-3.1.3/etc/hadoop/workers在该文件中增加如下内容&#xff1a; hadoop102 hadoop103 hadoop104 注意&#xff1a;该文件中添加的内容结尾不允许有空格&a…

K车模长得啥样?

根据 第十六届全国大学智能汽车竞赛竞速比赛规则-讨论稿 中的“单车拉力组”要求&#xff0c;车模使用K型车模&#xff0c;这是一个前后轮的电单车。那么究竟它长的啥样呢&#xff1f; 下面是由车模生产厂商提供的Solidwork车模3D模型截图。 ▲ 左上方的视图 ▲ 后上方的视图 …

K-Mean聚类算法

文章目录 0.前置基础0.1聚类简介 [3] [5]0.2 聚类与分类的区别[4] 1.K-Means算法思想2.K-Means算法原理及步骤2.1k-means聚类原理[3]【机器学习】全面解析Kmeans聚类算法&#xff08;Python&#xff09;_人工智能_032.2 k-means计算步骤[1]2.3 k-means术语[5]2.4 k-means开发流…

Top K问题【转载】

面试中&#xff0c;TopK&#xff0c;是问得比较多的几个问题之一&#xff0c;到底有几种方法&#xff0c;这些方案里蕴含的优化思路究竟是怎么样的&#xff0c;今天和大家聊一聊。 画外音&#xff1a;除非校招&#xff0c;我在面试过程中从不问TopK这个问题&#xff0c;默认大…

寻找第k元

要求&#xff1a;给定一个数组array[n],寻找大小排在第k的元素 思路一&#xff1a;最直接的思路就是先排序&#xff0c;这样可以直接通过数组下标找到第k大的元素&#xff0c;最好的快速排序时间复杂度为O(nlogn)。 思路二&#xff1a;我们可以在快速排序的基础上进行改进&am…

如何确定K-means算法中的k值?

1. K-means算法 k-means算法是机器学习中常用的聚类算法&#xff0c;原理简单实现容易&#xff0c;内存占用量也比较小。但使用这个方法时&#xff0c;需要事先指定将要聚合成的簇数。 在先验知识缺乏的情况下&#xff0c;想要确定是非常困难的。目前常用的用来确定的方法主要…

上证综指K线图

分享一下&#xff0c;7月份的学习成果。 使用SQL和Python绘制的上证指数K线图&#xff0c;在此Mark一下~千里之行&#xff0c;始于足下&#xff0c;要继续加油呀~ 具体代码略了&#xff0c;如有感兴趣的小伙伴&#xff0c;可以私信交流。

Django项目第一次打开加载不出css文件

你需要找到setting.py如下部分 修改你存放css文件和js等文件的目录 指定正确&#xff0c;本地就能跑了

QQ秀,销金窟

我已经很久没有用QQ秀了&#xff0c;一直坦然地穿着小裤衩和小背心&#xff0c;觉得这是成熟人士的标志。昨晚上听豆荚说她又买了大把Q币&#xff0c;准备去买QQ秀和会员&#xff0c;让我有点心动&#xff0c;于是跑到QQ秀官网去看了一下。 天哪&#xff0c;一年半载不见&…

机器学习入门——K近邻算法

引言 本文介绍本系列的第一个机器学习算法——K近邻算法(K-Nearest Neighbors,knn)。 它的思想很简单&#xff0c;用到的数学知识也比较少(只用到了求距离公式)&#xff0c;效果好。 本文还会涉及到和应用机器学习相关的问题的处理方式。 上一篇&#xff1a;机器学习入门——…

K-mean clustering(K均值聚类算法)

一、聚类与分类的区别 分类&#xff1a;类别已知&#xff0c;通过对已知分类的数据进行训练和学习&#xff0c;找到这些不同类的特征&#xff0c;再对未分类的数据进行分类。是有监督学习。 聚类&#xff1a;事先不知道数据会分为几类&#xff0c;通过聚类分析将数据聚合成几…

编程初学者如何在GitHub寻找适合自己的小项目?

即使作为编程新手&#xff0c;刚刚接触GitHub&#xff0c;也建议你从最简单的项目入手&#xff0c;而不是单纯研究大量理论。 这个⭐18.5k的优&#xff08;宅&#xff09;秀&#xff08;男&#xff09;项目&#xff1a;komeiji-satori/Dress就非常适合初学者Pick。 作为全球最…

K-means方法总结(附代码)

K-means方法总结&#xff08;附代码&#xff09; 这一周事情较多&#xff0c;不得已先放弃了验证码分割部分的卷积神经网络的学习&#xff0c;先写两篇关于聚类方法的内容&#xff0c;分别是k-means和混合高斯模型。因为之前的论文中有关于k-means方法的字符分割方法&#xff…

【数据结构】二叉树篇|超清晰图解和详解:二叉树的序列化和反序列化

博主简介&#xff1a;努力学习的22级计算机科学与技术本科生一枚&#x1f338;博主主页&#xff1a; 是瑶瑶子啦每日一言&#x1f33c;: 你不能要求一片海洋&#xff0c;没有风暴&#xff0c;那不是海洋&#xff0c;是泥塘——毕淑敏 目录 一、核心二、题目2.1:前序遍历2.2&…

2023.08.27 学习周报

文章目录 摘要文献阅读1.题目2.重点3.引言4.方法5.实验结果6.结论 深度学习Majorization-Minimization算法1.基本思想2.要求3.示意图 总结 摘要 This week, I read a computer science on the prediction of atmospheric pollutants in urban environments based on coupled d…

Xposed API详解

Xposed API详解 Hook修改变量Hook普通方法回调函数XC_MethodHookXC_MethodReplacement Hook获取参数与返回值获取参数获取返回值 Hook构造函数无参构造有参构造 Hook复杂函数Hook自定义类参数Hook替换函数与函数置空替换函数函数置空 Hook内部类与匿名类内部类匿名类 Xposed主动…

【Python】PySpark

前言 Apache Spark是用于大规模数据&#xff08;large-scala data&#xff09;处理的统一&#xff08;unified&#xff09;分析引擎。 简单来说&#xff0c;Spark是一款分布式的计算框架&#xff0c;用于调度成百上千的服务器集群&#xff0c;计算TB、PB乃至EB级别的海量数据…

Xposed常用逆向函数

1. 创建Xposed工程 在Android Studio中新建一个app工程&#xff0c;修改其中的 AndroidManifest.xml 文件&#xff0c;在<application></application>标签中增加如下代码 <meta-dataandroid:name"xposedmodule"android:value"true" />…