golang学习笔记——select 判断语句
判断语句
Go 语言提供了以下几种条件判断语句:
| 语句 | 描述 |
|---|---|
| if 语句 | if 语句 由一个布尔表达式后紧跟一个或多个语句组成。 |
| if…else 语句 | if 语句 后可以使用可选的 else 语句, else 语句中的表达式在布尔表达式为 false 时执行。 |
| if 嵌套语句 | 你可以在 if 或 else if 语句中嵌入一个或多个 if 或 else if 语句。 |
| switch 语句 | switch 语句用于基于不同条件执行不同动作。 |
| select 语句 | select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。 |
注意:Go 没有三目运算符,所以不支持 ?: 形式的条件判断。
本文只介绍select 语句
基本 select 语法
select 是 Go 中的一个控制结构,类似于 switch 语句。
select 语句只能用于通道操作,每个 case 必须是一个通道操作,要么是发送要么是接收。
select 语句会监听所有指定的通道上的操作,一旦其中一个通道准备好就会执行相应的代码块。
如果多个通道都准备好,那么 select 语句会随机选择一个通道执行。如果所有通道都没有准备好,那么执行 default 块中的代码。
Go 编程语言中 select 语句的语法如下:
select {case <- channel1:// 执行的代码case value := <- channel2:// 执行的代码case channel3 <- value:// 执行的代码// 你可以定义任意数量的 casedefault:// 所有通道都没有准备好,执行的代码
}
以下描述了 select 语句的语法:
-
每个 case 都必须是一个通道
-
所有 channel 表达式都会被求值
-
所有被发送的表达式都会被求值
-
如果任意某个通道可以进行,它就执行,其他被忽略。
-
如果有多个 case 都可以运行,select 会随机公平地选出一个执行,其他不会执行。
否则:
- 如果有 default 子句,则执行该语句。
- 如果没有 default 子句,select 将阻塞,直到某个通道可以运行;Go 不会重新对 channel 或值进行求值。
select 语句应用演示1
package mainimport ("fmt""time"
)func main() {c1 := make(chan string)c2 := make(chan string)go func() {time.Sleep(1 * time.Second)c1 <- "one"}()go func() {time.Sleep(2 * time.Second)c2 <- "two"}()for i := 0; i < 2; i++ {select {case msg1 := <-c1:fmt.Println("received", msg1)case msg2 := <-c2:fmt.Println("received", msg2)}}
}
以上代码执行结果为:
received one
received two
以上实例中,我们创建了两个通道 c1 和 c2。
select 语句等待两个通道的数据。如果接收到 c1 的数据,就会打印 “received one”;如果接收到 c2 的数据,就会打印 “received two”。
select 语句应用演示2
以下实例中,我们定义了两个通道,并启动了两个协程(Goroutine)从这两个通道中获取数据。在 main 函数中,我们使用 select 语句在这两个通道中进行非阻塞的选择,如果两个通道都没有可用的数据,就执行 default 子句中的语句。
以下实例执行后会不断地从两个通道中获取到的数据,当两个通道都没有可用的数据时,会输出 “no message received”。
package mainimport "fmt"func main() {// 定义两个通道ch1 := make(chan string)ch2 := make(chan string)// 启动两个 goroutine,分别从两个通道中获取数据go func() {for {ch1 <- "from 1"}}()go func() {for {ch2 <- "from 2"}}()// 使用 select 语句非阻塞地从两个通道中获取数据for {select {case msg1 := <-ch1:fmt.Println(msg1)case msg2 := <-ch2:fmt.Println(msg2)default:// 如果两个通道都没有可用的数据,则执行这里的语句fmt.Println("no message received")}}
}
select 语句的使用场景
以下是一些 select 语句的使用场景:
-
等待多个通道的消息(多路复用)
当我们需要等待多个通道的消息时,使用
select语句可以非常方便地等待这些通道中的任意一个通道有消息到达,从而避免了使用多个goroutine进行同步和等待。 -
超时等待通道消息
当我们需要在一段时间内等待某个通道有消息到达时,使用
select语句可以与time包结合使用实现定时等待。 -
在通道上进行非阻塞读写
在使用通道进行读写时,如果通道没有数据,读操作或写操作将会阻塞。但是使用
select语句结合default分支可以实现非阻塞读写,从而避免了死锁或死循环等问题。
因此,select 的主要作用是在处理多个通道时提供了一种高效且易于使用的机制,简化了多个 goroutine 的同步和等待,使程序更加可读、高效和可靠。
channel 与 select 结合的常见用途
利用 default 分支避免阻塞
select 的 default 分支语义:当所有 case 语句里读/写 channel 阻塞时,会执行 default!
无论 channel 是否有 buffer。
有些时候,我们可能不希望阻塞在写入 channel 上,那可以利用 select default 的特性,这样封装一个函数,当写入阻塞时,返回一个 false,让外界可以处理阻塞的情况:
func tryWriteChannel(c chan<- int, value int) bool {select {case c <- valuereturn truedefault: //其他没就绪时,会执行return false}
}
这样使用:
//active <- 1 //之前直接写 channel,如果满了,就会阻塞
writed := tryWriteChannel(active, 1) //改成这样,可以在阻塞时,处理相关逻辑
if !writed {log.Println("failed to write channel")return
}
实现超时
假如我们想在一个 channel 的读/写操作上加一个超时逻辑,可以通过这样实现: 在 select 代码块中,加一个 case,这个 case 会在超时后执行,这样会结束其他 case。
比如这样:
func tryGetSemaphore(c chan<- struct{}) bool {select {case c <- struct {}{}:return truecase <- time.After(1 * time.Second): //在写 channel 的基础上,额外加一个情况,超时情况log.Println("timeout!!!")//1s 后返回,可以在这里做超时处理return true}
}
及时调用 timer 的 Stop 方法回收 Timer 资源。
心跳机制
循环执行一个额外的 case,这个 case 会定时返回。
func worker() {heartbeat := time.NewTicker(30 * time.Second)defer heartbeat.Stop()for {select {case <-c:// ... do some stuffcase <- heartbeat.C://... do heartbeat stuff}}
}
time.NewTicker 会创建一个定时执行的心跳,可以把这个 ticker channel 读取的操作放到一个 case 里,这样 select 代码块就会定时执行一次。
相关文章:
golang学习笔记——select 判断语句
判断语句 Go 语言提供了以下几种条件判断语句: 语句描述if 语句if 语句 由一个布尔表达式后紧跟一个或多个语句组成。if…else 语句if 语句 后可以使用可选的 else 语句, else 语句中的表达式在布尔表达式为 false 时执行。if 嵌套语句你可以在 if 或 else if 语句…...
FLMix: 联邦学习新范式——局部和全局的结合
文章链接:Federated Learning of a Mixture of Global and Local Models 发表期刊(会议): ICLR 2021 Conference(机器学习顶会) 目录 1. 背景介绍2. 传统联邦学习3. FL新范式理论逻辑重要假设解的特性 本博客从优化函…...
为什么嵌入式没有35岁危机?
为什么嵌入式没有35岁危机? 在当今数字化时代,IT行业变化迅速,技术的更新迭代速度惊人。然而,有一个技术领域却能够在这个竞争激烈的行业中稳步前行,而且不受35岁危机所困扰,那就是嵌入式技术。 嵌入式技术是指将计算…...
PostgreSQL设置主键从1开始自增
和MySQL不同,在 PostgreSQL 中,设置主键从1开始自增并重新开始自增是通过序列(sequence)来实现的。以下是步骤: 步骤1:创建一个序列 CREATE SEQUENCE your_table_id_seqSTART 1INCREMENT 1MINVALUE 1MAXV…...
Vue数据绑定
在我们Vue当中有两种数据绑定的方法 1.单向绑定 2.双向绑定 让我为大家介绍一下吧! 1、单向绑定(v-bind) 数据只能从data流向页面 举个例子: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"…...
js写轮播图,逐步完善
目录 1、自动轮播 2、点击更换 3、自动播放加左右箭头点击切换 4、完整版轮播图 1、自动轮播 用定时器setInterval()来写,可以实现自动播放 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><met…...
算法-链表-简单-相交、反转、回文、环形、合并
记录一下算法题的学习5 在写关于链表的题目之前,我们应该熟悉回忆一下链表的具体内容 什么是链表: 链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,…...
【500强 Kubernetes 课程】第3章 运行docker容器
一 - 三 ,docker基础操作见 第2章7节 四、docker部署web网站 1、安装 nginx (适合场景:学习 - 略) 2、docker 安装 nginx Stage 1 :docker hub 上 搜索 nginx 镜像 Stage 2:拉取官方镜像 Stage 3&…...
Python中表格插件Tabulate的用法
目录 一、引言 二、Tabulate插件安装与导入 三、Tabulate基本用法 1、创建表格: 2. 格式化表格: 3. 表格转置: 4、合并单元格: 5、指定每列的格式: 6、指定每行的格式: 7、使用自定义表格格式&am…...
缺陷分级(过程质量bug分级)
缺陷按照其影响的严重程度,从高到低分成5级,分别为致命(Blocker)、严重(Critical)、一般(Major)、轻微(Minor)以及建议(Enhancement)。…...
pycharm/vscode 配置black和isort
Pycharm blackd Pycharm中有插件可以实现后台服务运行black:BlackConnect 安装 在python中安装blackd 配置 Pycharm isort pycharm中,isort没有插件,暂使用外部工具实现,外部工具也可添加快捷键实现快捷对文件、文件夹进行fo…...
python列出本地文件路径
按照之前的设想,如果要罗列出本地文件的列表,那不是需要不断的判断文件夹里面的文件夹吗?或者需要使用递归函数本身,才能达到目的吧?没想到使用pop这个函数就可以了。pop是取出元素,那列表里就少了一个&…...
在JavaScript中检查一个数字是否是另一个数字的倍数
使用%模数运算符 为了检查一个数字是否是另一个数字的倍数,我们可以使用JavaScript中的% modulo运算符。 modulo% 操作符返回第一个数字在第二个数字上的余数,例如:10 % 2 0 ,所以如果我们得到一个余数0 ,那么给定的数…...
计算机网络五层协议的体系结构
计算机网络中两个端系统之间的通信太复杂,因此把需要问题分而治之,通过把一次通信过程中涉及的所有问题分层归类来进行研究和处理 体系结构是抽象的,实现是真正在运行的软件和硬件 1.实体、协议、服务和服务访问点 协议必须把所有不利条件和…...
MySQL 运算符二
逻辑运算符 逻辑运算符用来判断表达式的真假。如果表达式是真,结果返回 1。如果表达式是假,结果返回 0。 运算符号作用NOT 或 !逻辑非AND逻辑与OR逻辑或XOR逻辑异或 1、与 mysql> select 2 and 0; --------- | 2 and 0 | --------- | 0 | -…...
【SA8295P 源码分析】121 - MAX9295A 加串器芯片手册分析 及初始化参数分析
【SA8295P 源码分析】121 - MAX9295A 加串器芯片手册分析 及初始化参数分析 一、MAX9295A 芯片特性1.1 GPIO 引脚说明1.2 功能模块框图1.3 时序分析1.3.1 GMSL2 Lock Time:25 ms1.3.2 视频初始化延时:1.1ms + 17000 x t(PCLK)1.3.3 High-Speed Data Transmission in Bursts1.…...
问题汇总20231103
文章目录 前言问题汇总1.所有操作系统在CPU层面上是不是都为时间片轮转的形式处理程序?只是任务调度的调度算法不同?那多线程的本质也是时间片吗?只不过很小?2.Mcu和mpu的本质区别3.下载HAL库步骤4.RAM,ROM,SRAM,SDRAM,DDR内存5.编…...
65.Undertow代替Tomcat
SpringBoot中我们既可以使用Tomcat作为Http服务,也可以用Undertow来代替。Undertow在高并发业务场景中,性能优于Tomcat。所以,如果我们的系统是高并发请求,不妨使用一下Undertow,你会发现你的系统性能会得到很大的提升…...
前端mockjs使用方式[express-mockjs]
前提 现在基本上都是前后端分离项目的开发,而前端对于UI界面开发完毕之后往往都需要等待后端的接口提供,因此为了解决这个问题,这里提供一个由express和mockjs结合的本地服务应用项目,可以前端随意造数据配合UI页面进行开发。 个…...
矿区安全检查VR模拟仿真培训系统更全面、生动有效
矿山企业岗位基数大,生产过程中会持续有新入矿的施工人员及不定期接待的参观人员,下井安全须知培训需求量大。传统实景拍摄的视频剪辑表达方式有限,拍摄机位受限,难以生动表达安全须知的内容,且井下现场拍摄光线不理想…...
ViGEmBus虚拟手柄驱动深度解析与实战指南
ViGEmBus虚拟手柄驱动深度解析与实战指南 【免费下载链接】ViGEmBus Windows kernel-mode driver emulating well-known USB game controllers. 项目地址: https://gitcode.com/gh_mirrors/vi/ViGEmBus 你是否曾经遇到过这样的困境:手头有一款独特的游戏控制…...
[具身智能-855]:什么是AI应用?AI 应用、AI 模型、AI Agent三者区别?
一、定义AI 应用:搭载人工智能技术,具备智能理解、推理、生成、识别、决策能力,能自主完成人类事务的软件、程序、系统、设备。二、狭义 AI 应用(纯 AI 工具,最常见)专门靠 AI 干活,一眼看出是 …...
机器人路径规划:安全性与最优性的平衡算法解析
1. 路径规划中的安全性与最优性平衡难题在机器人导航领域,路径规划算法始终面临一个核心矛盾:如何同时保证路径的最优性和安全性。传统A*算法追求最短路径,却常常让机器人贴着障碍物边缘行走;而基于Voronoi图的规划方法虽然能最大…...
3个关键策略:安全使用ViVeTool-GUI控制Windows隐藏功能
3个关键策略:安全使用ViVeTool-GUI控制Windows隐藏功能 【免费下载链接】ViVeTool-GUI Windows Feature Control GUI based on ViVe / ViVeTool 项目地址: https://gitcode.com/gh_mirrors/vi/ViVeTool-GUI ViVeTool-GUI是一款基于ViVe/ViVeTool的Windows功能…...
AI如何悄然重塑日常生活:从工具到环境的四层渗透
1. 这不是未来预告,是此刻正在发生的日常渗透“AI正在 quietly taking over your daily life”——这句话里最值得玩味的,不是“AI”,也不是“taking over”,而是那个轻描淡写的quietly(悄然地)。它不敲锣打…...
OpCore-Simplify:三步搞定OpenCore EFI配置的终极解决方案
OpCore-Simplify:三步搞定OpenCore EFI配置的终极解决方案 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 还在为复杂的OpenCore EFI配置而…...
Mathtype高手私藏技巧:自定义快捷键把常用公式变成“一键宏”
Mathtype效率革命:用宏快捷键打造专属公式输入流 在科研论文写作、工程计算报告或是数学教材编撰中,频繁输入重复的复杂公式是许多专业人士的日常痛点。当你在推导过程中第十次输入那个包含三重积分、特殊符号和特定排版的公式时,是否渴望有一…...
Unity启动Logo跳过指南:三步实现多平台秒开启动
1. 为什么Unity启动Logo不是“装饰”,而是必须被正视的交付环节你刚打包完一个Unity游戏,兴冲冲地发给测试同事,对方点开exe——先是一片黑屏,接着弹出那个熟悉的、带渐变动画的Unity Logo,再过3秒才进主菜单。测试发来…...
150块淘来的Nvidia Grid K2,如何在ESXi 6.7上稳定分配vGPU?我的翻车与修复实录
150元Nvidia Grid K2显卡的ESXi 6.7虚拟化实战:从硬件检测到vGPU稳定分配全指南 在虚拟化环境中部署专业显卡一直是技术爱好者和小型实验室的热门话题。当预算有限时,二手市场上的老款专业显卡如Nvidia Grid K2就成为了极具吸引力的选择。这款发布于2013…...
