go语言判断管道是否关闭的误区
前言
本文是探讨的是"在Go语言中,我们是否可以使用读取管道时的第二个返回值来判断管道是否关闭?"
样例
在Go语言中,我们是否可以使用读取管道时的第二个返回值来判断管道是否关闭? 可以看下面的代码
package mainimport "fmt"func main() {// 创建一个整型管道ch := make(chan int)// 启动一个协程往管道发送数据go func() {for i := 0; i < 5; i++ {ch <- i}// 关闭管道close(ch)}()// 能否判断管道是否关闭?if _, ok := <-ch; !ok {fmt.Println("管道已关闭")}
}
探讨 管道的数据结构
在探讨这个问题之前,我们先来了解一下管道的数据结构,从go的源码,我们可以知道,管道是被定义为一个名为hchan的结构体:
type hchan struct {qcount uint //当前队列中剩余的元素个数dataqsiz uint // 环形队列管道容积buf unsafe.Pointer // 环形队列指针elemsize uint16 // 元素大小closed uint32 // 标识管道关闭的状态elemtype *_type // 元素类型recvq waitq // 等待的读元素的协程队列sendq waitq // 等待的写元素的协程队列...
}
其中,有一个属性是我们应该关注的,那就是closed,这玩意标识了管道是否关闭,这玩意为1代表关闭了,为0代表是开启的.
详细分析
好的,接下来我们继续本文探讨的问题在Go语言中,我们是否可以使用管道的第二个返回值来判断管道是否关闭?
先给出结论 : 从严格意义上来讲是不可以的,其实表示是否成功读取数据,但是在缓存区为0的时候,ok的状态和管道状态是一致的,所以会被误认为,这个ok是代表管道的状态
可以看下面的例子
package mainimport ("fmt""time"
)func main() {a2 := make(chan int, 2)go demo(a2)value2, ok2 := <-a2fmt.Printf("value2:%v,ok2:%v\n", value2, ok2)time.Sleep(3 * time.Second)value3, ok3 := <-a2fmt.Printf("value3:%v,ok3:%v\n", value3, ok3)}func demo(a chan int) {defer func() {close(a)fmt.Println("管道已经关闭")}()a <- 1a <- 2
}
解释一下运行流程
- 首先创建了一个缓存区为2的管道a2
- 然后用go关键字
将demo函数开辟出一个新的协程运行,此时demo和main是同一级的关系,同时运行,此时main函数会继续向下执行,发现是从管道中读取一个元素,然后就会等待demo函数会向管道中传入值,demo函数的运行过程是这样的,它发现管道a2的缓存是2,所以刚好把元素存入,然后就执行关闭管道,然后demo协程销毁 - main函数继续执行,接收到a2管道的一个元素之后,然后返回value2和ok2,然后进行打印
- 然后休眠3秒钟
- 然后继续读取a2管道的元素,得到value3和ok3,然后打印

ok2和ok3都为true
’ 管道已经关闭 ’ 这是最先打印的,无论运行多少次,都是一样的,而且我还特地将main函数暂停了3秒,所以我可以保证demo函数已经执行完毕,demo协程已经销毁,然后再执行的第二个管道的数据的读取
逐步调试
- 那我们调试一下,可以发现,执行了make函数创建管道之后,管道没有关闭,我前面特意提了管道的数据结构,其中closed是标识管道是否关闭的

- 继续调试,我们可以发现,在读取完管道a2的第一个值赋值给value2和ok2的时候,此时通道已经关闭

- value2的值为1,ok2为true

- 继续调试,通道还是关闭状态,但是ok3的值还是true,看下面的第二张图


所以读取管道元素传来的第二个值,并不是代表管道是否关闭!
那它代表什么?
其实是代表读取数据是否成功,或者说代表缓存区是否还有数据
首先我们要知道, 关闭了的管道, 我们还是可以进行读取的, 这个设定是因为有缓存的存在, 但是如果管道关闭了的话,又没有值,读取的话,会是类型的默认值和false,也就是读取未成功
当然如果是缓存区为0的情况,ok的值和管道的状态是一致的
var c = make(chan int)
close(c)
value, ok := <-c
fmt.Printf("value:%v \nok:%v \n", value, ok)
运行结果:

相关文章:
go语言判断管道是否关闭的误区
前言 本文是探讨的是"在Go语言中,我们是否可以使用读取管道时的第二个返回值来判断管道是否关闭?" 样例 在Go语言中,我们是否可以使用读取管道时的第二个返回值来判断管道是否关闭? 可以看下面的代码 package mainimport "fmt"…...
如何轻松使用 ChatGPT 进行论文大纲和创作
ChatGPT能够编写复杂的代码、博客文章等,它可以帮助我们做很多事情。今天本篇文章分享的主要内容如何利用 ChatGPT 来撰写论文文章。下面会介绍如何轻松使用 ChatGPT 进行论文大纲和创作! 1、使用 ChatGPT 确定主题 文章非常重要的一个部分就是主题。如…...
【深蓝学院】手写VIO第6章--视觉前端--笔记
第5章相关内容,还是CSDN的传统Markdown编辑器好用。 视觉前段在14讲课程中已经讲过,这里再简单复习一下。 1. 前端工作的定性比较,分析 这一节讲了很多关于前端的方法框架的对比讨论,后面看完了相关的论文之后强烈建议再回来听一…...
用例图 UML从入门到放弃系列之三
1.说明 关于用例图,这篇文章我将直接照搬罗伯特.C.马丁老爷子在《敏捷开发》一书种的第17章,并配上自己的理解,因为这一章写的实在是太精彩了,希望能够分享给大家,共勉。以下是老爷子的原文中文翻译以及豆芽的个人解读…...
NLP大模型
大模型 1、大模型的模型结构 一般指一亿参数以上的模型。 目前以Transformer为基础自回归生成大致可以分为三种架构: Encoder-only的模型,如BERT Encoder-Decoder的模型,如T5。 Decoder-Only的模型,如GPT系列。...
Python- 将一个字符串列表连接成一个单独的字符串
Python中一个常用的技巧:将一个字符串列表连接成一个单独的字符串。 ,.join(list) 是使用Python的 str.join() 方法。 详细解析: join() 方法: 是一个字符串方法,意味着在一个字符串上调用它。它需要一个参数,通常是一个列表或任…...
深眸科技自研AI视觉分拣系统,实现物流行业无序分拣场景智慧应用
在机器视觉应用环节中,物体分拣是建立在识别、检测之后的一个环节,通过机器视觉系统对图像进行处理,并结合机械臂的使用实现产品分类。 通过引入视觉分拣技术,不仅可以实现自动化作业,还能提高生产线的生产效率和准确…...
吴恩达《微调大型语言模型》笔记
微调(fine-tuning)就是利用特有数据和技巧将通用模型转换为能执行具体任务的一种方式。例如,将 GPT-3 这种通用模型转换为诸如 ChatGPT 这样的专门用于聊天的模型。或者将 GPT-4 转换为诸如 GitHub Coplot 这样的专门用于写代码的模型。 这里…...
Java中的Servlet
Java中的Servlet 在Java中,Servlet是一种用于处理Web请求的服务器端组件。Servlet生命周期是Servlet在运行时所经历的一系列阶段,每个阶段都调用特定的方法。以下是Servlet生命周期内调用的方法过程: 初始化阶段(Initialization&…...
Flutter配置Android SDK路径
在使用VSCode作为开发Flutter的工具时,当选择调试设备时,通常看不到android的模拟器,只能看到Chrome之类的。 原因就是Flutter找不到Android的SDK路径,所以无法识别模拟器,我们用flutter doctor命令检查环境时…...
jwt的基本介绍
说出我的悲惨故事给大家乐呵乐呵:公司刚来了一个实习生,老板让他写几个接口给我,我页面还没画完呢。他就把接口给我了,我敲开心,第一次见这么高效率的后端。但我很快就笑不出来了。他似乎不知道HTTP通信是无状态的。他…...
常见Vue事件修饰符浅析
一、.stop修饰符 .stop修饰符代表event.stopPropagation(),加上这个修饰符,就等于在方法中加上了这句代码。 <!--阻止单击事件继续传播--> <a click.stop"doThis"></a>上面的代码等同于如下代码。 <!--阻止单击事件继…...
怎样开始用selenium进行自动化测试?
如果您刚开始使用 Selenium 进行自动化测试,以下是建议的步骤。 1、安装 Selenium 首先,您需要安装 Selenium。Selenium 支持多种编程语言,如 Python、Java、C# 等。可以通过 pip 命令在 Python 中安装 Selenium: pip install …...
二维数组多次排序 或 嵌套list多次排序
可以排序int[ ][ ]的顺序,也可以排序List<List<Integer>> 顺序 为便于理解,以力扣原题为例:1333.餐厅过滤器 原题中给了一个双重数组,并要求返回一个List<Integer>。 方法1: 会用流的,…...
Flutter - 波浪动画和lottie动画的使用
demo 地址: https://github.com/iotjin/jh_flutter_demo 代码不定时更新,请前往github查看最新代码 波浪动画三方库wave lottie动画 Lottie 是 Airbnb 开发的一款能够为原生应用添加动画效果的开源工具。具有丰富的动画效果和交互功能。 # 波浪动画 https://pub-web…...
忘记压缩包密码?解决方法一键找回,省时又便捷!
使用在线rar/zip解密工具,找回rar/zip密码并解密压缩包的方法非常简单。具体步骤如下:首先,在百度上搜索“密码帝官网”,这是一个专业的解密服务网站。然后,点击搜索结果中的链接,进入官网首页。在页面上方…...
“UTONMOS”掀起元宇宙游戏热潮,全球发展前景广阔
我们都知道,市面上无论是PC端的网游还是移动端手游,它如果要做到源源不断的内容输出,不仅取决于游戏公司产品质量和业绩,也与公司的决策和市场沟通密不可分。 元宇宙游戏市场受到关注 近年来,元宇宙游戏市场逐渐升温…...
用idea工具scala 和 Java开发 spark案例:WordCount
目录 一 环境准备 二 scala代码编写 三 java 代码编写 一 环境准备 创建一个 maven 工程 添加下列依赖 <dependency><groupId>org.apache.spark</groupId><artifactId>spark-core_2.12</artifactId><version>${spark.version}</vers…...
【git merge/rebase】详解合并代码、解决冲突
目录 1.概述 2.merge 3.rebase 4.merge和rabase的区别 5.解决冲突 1.概述 在实际开发中,一个项目往往是多个人一起协作的,头天下班前大家把代码交到远端仓库,第二天工作的第一件事情都是从服务器上拉最新的代码,保证代码版本…...
nrm,npm源的管理工具
npm手动切换淘宝源 查看当前的仓库 npm config get registry设置成淘宝源 npm config set registry https://registry.npmmirror.com/设置回官方源 npm config set registry https://registry.npmjs.org/手动切换不免不太方便,而且网上很多资料淘宝源还是过期的链接…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案
随着新能源汽车的快速普及,充电桩作为核心配套设施,其安全性与可靠性备受关注。然而,在高温、高负荷运行环境下,充电桩的散热问题与消防安全隐患日益凸显,成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
