当前位置: 首页 > news >正文

Go 协程通道使用注意

目录

关闭channel

引入

 不关闭通道是有风险的,主要存在两条:

如何优雅的关闭?

1.只有一个发送者

2.多个发送者

判断通道是否关闭

有缓存和无缓存的通道有什么区别?

错误的关闭通道


关闭channel

close(chan):关闭通道并不会丢失里面的数据,只是让读取通道数据的时候不会读完之后一直阻塞等待新数据写入。

引入

看一看下面的例子:

ch := make(chan int, 1)
ch <- 11
// close(ch) // 如果不关闭,下面会引发死锁// 通道没有关闭的时候会阻塞,程序会永远等待从通道中接收值。而且由于没有其他goroutine来关闭通道,这个阻塞状态将会持续下去,从而引发死锁。
for v := range ch {fmt.Println(v)
}

 不关闭通道是有风险的,主要存在两条:

  1. 出现死锁:如果通道不会再被使用但未关闭,接收者可能会一直等待数据,导致死锁或无意义的等待。
  2. 出现资源泄漏:未关闭的通道可能会导致资源泄漏,因为垃圾收集器不会回收未关闭的通道。而且还要消耗电脑的性能来维护这条管道。

如何优雅的关闭?

在关闭管道的时候,我们要注意:正确地决定何时关闭通道、确保通道不会被多次关闭。(多次关闭同一个通道会报panic)

1.只有一个发送者

如果只有一个发送者,那么这个发送者在完成所有发送操作后可以直接关闭通道:

package mainimport ("fmt""time"
)// 边入边出
func main() {c := make(chan int, 5)go fibonacci(10, c)for v := range c {fmt.Println("out:", time.Now())fmt.Println(v)}
}// 应该由发送数据的一方关闭通道,当数据发送完毕后就是关闭通道的时候。
func fibonacci(n int, c chan int) {x, y := 0, 1for i := 0; i < n; i++ {c <- xfmt.Println("in:", time.Now())time.Sleep(100)x, y = y, x+y}close(c)
}// 大致运行结果:
// in: 2024-07-16 16:00:34.637655 +0800 CST m=+0.000171297
// out: 2024-07-16 16:00:34.637681 +0800 CST m=+0.000197020
// in: 2024-07-16 16:00:34.637952 +0800 CST m=+0.000467725
// 0
// in: 2024-07-16 16:00:34.637963 +0800 CST m=+0.000478508
// out: 2024-07-16 16:00:34.637968 +0800 CST m=+0.000483915
// 1
// in: 2024-07-16 16:00:34.637976 +0800 CST m=+0.000491801
// in: 2024-07-16 16:00:34.637983 +0800 CST m=+0.000499051
// out: 2024-07-16 16:00:34.637978 +0800 CST m=+0.000494157
// 1
// out: 2024-07-16 16:00:34.637999 +0800 CST m=+0.000514485
// 2
// out: 2024-07-16 16:00:34.638006 +0800 CST m=+0.000522241
// 3
// out: 2024-07-16 16:00:34.638013 +0800 CST m=+0.000528591
// 5
// in: 2024-07-16 16:00:34.637988 +0800 CST m=+0.000504017
// in: 2024-07-16 16:00:34.638039 +0800 CST m=+0.000555021
// in: 2024-07-16 16:00:34.638045 +0800 CST m=+0.000561340
// in: 2024-07-16 16:00:34.638049 +0800 CST m=+0.000564725
// in: 2024-07-16 16:00:34.638055 +0800 CST m=+0.000570642
// out: 2024-07-16 16:00:34.638052 +0800 CST m=+0.000568007
// 8
// out: 2024-07-16 16:00:34.638095 +0800 CST m=+0.000610606
// 13
// out: 2024-07-16 16:00:34.638103 +0800 CST m=+0.000619251
// 21
// out: 2024-07-16 16:00:34.63811 +0800 CST m=+0.000626188
// 34

2.多个发送者

当有多个发送者时,可以使用 sync.WaitGroup 来协调这些发送者,并在所有发送者完成后由一个协程关闭通道:

package mainimport ("fmt""sync"
)func main() {ch := make(chan string)var wg sync.WaitGroup// 启动3个协程发送数据for i := 1; i <= 5; i++ {wg.Add(1)go func(num int) {defer wg.Done()for j := 'a'; j <= 'e'; j++ {ch <- fmt.Sprintf("协程%d:%c", num, j)}}(i)}// 启动一个协程来等待所有发送者完成并关闭通道go func() {wg.Wait()close(ch)}()// 接收数据for val := range ch {fmt.Println(val)}fmt.Println("通道已关闭,结束接收")
}

判断通道是否关闭

v, ok := <-ch

如果 ok 为 true,表示成功从 channel 中接收到一个值,并且 channel 还没有关闭。如果 ok 为 false,表示 channel 已经关闭。

当一个 channel 已经关闭而且其中的元素已经全部被取出时,再从管道中取出数据会返回该元素类型的零值,并且 ok 会被设置为 false。这样的检查是为了防止在已关闭的 channel 上进行接收操作时,引发 panic。因为在已关闭的 channel 上进行接收操作会立即返回零值,但如果不进行检查,可能会误认为是从 channel 中接收到了有效的数据。因此,通过检查 ok,我们可以确定是否成功接收到了有效的值。

    c := make(chan int, 5)c <- 1c <- 2c <- 3close(c)v1, ok := <-cfmt.Println(v1, ok) // 1 truev1, ok = <-cfmt.Println(v1, ok) // 2 truev1, ok = <-cfmt.Println(v1, ok) // 3 truev1, ok = <-cfmt.Println(v1, ok) // 0 falsev1, ok = <-cfmt.Println(v1, ok) // 0 false

有缓存和无缓存的通道有什么区别?

参考下面链接:

golang channel有无缓冲区的区别

错误的关闭通道

错误一:多次关闭同一个通道

    c := make(chan int, 5)for i := 0; i < 5; i++ {defer close(c) // 报panic:同一个通道关闭了多次}

错误二:资源泄漏

    for i := 0; i < 5; i++ {c := make(chan int, 5)defer close(c)}

看起来没有错误,运行出来也没有错误。但是可能会导致资源泄漏,因为每次循环迭代中创建的通道不会立即关闭,导致内存和其他资源的泄漏。这五个管道的关闭时间都是在:所在函数运行完毕的时候关闭的。而不是本次循环结束后就立刻关闭。

相关文章:

Go 协程通道使用注意

目录 关闭channel 引入 不关闭通道是有风险的&#xff0c;主要存在两条&#xff1a; 如何优雅的关闭&#xff1f; 1.只有一个发送者 2.多个发送者 判断通道是否关闭 有缓存和无缓存的通道有什么区别&#xff1f; 错误的关闭通道 关闭channel close(chan)&#xff1a;关…...

React基础学习-Day04

React基础学习-Day04 常见的钩子函数及基础使用方式 1.useState useState 是 React 的一个 Hook&#xff0c;用于在函数组件中添加状态。它返回一个状态变量和一个更新该状态的函数。与类组件的 this.state 和 this.setState 相对应&#xff0c;useState 让函数组件也能拥有…...

python爬虫获取网易云音乐评论歌词以及歌曲地址

python爬虫获取网易云音乐评论歌词以及歌曲地址 一.寻找数据接口二.对负载分析三.寻找参数加密过程1.首先找到评论的请求包并找到发起程序2.寻找js加密的代码 四.扣取js的加密源码1.加密函数参数分析①.JSON.stringify(i0x)②bse6Y(["流泪", "强"])③bse6Y…...

中间件的理解

内容来源于学习网站整理。【一看就会】什么是前端开发的中间件&#xff1f;_哔哩哔哩_bilibili 每日八股文~白话说mq&#xff0c;消息中间件_哔哩哔哩_bilibili 例如&#xff1a; 1&#xff09;两个人打电话&#xff0c;中间的通信网络就是中间件。 2&#xff09;菜鸟驿站&…...

django实现用户的注册、登录、注销功能

创建django项目的步骤&#xff1a;Django项目的创建步骤-CSDN博客 一、前置工作 配置数据库&#xff0c;设置数据库引擎为mysql 1、在settings文件中找到DATABASES, 配置以下内容 DATABASES {"default": {ENGINE: django.db.backends.mysql, # 数据库引擎NAME: dja…...

【JAVA 常用API】数据库字段存储JSON格式数据,JAVA中如何将List<Entity>或者对象实体转换为字符串

在Java中&#xff0c;可以使用第三方库如Jackson或Gson来进行JSON的转换。这些库提供了将Java对象转换为JSON字符串的方法。 一&#xff1a;Gson API转Json Getter Setter NoArgsConstructor AllArgsConstructor ToString Builder public class Person {private String name;p…...

AI算不出9.11和9.9哪个大?六家大模型厂商总结了这些原因

大模型“答对”或“答错”其实是个概率问题。关于“9.11和9.9哪个大”&#xff0c;这样一道小学生难度的数学题难倒了一众海内外AI大模型。7月17日&#xff0c;第一财经报道了国内外“12个大模型8个都会答错”这道题的现象&#xff0c;大模型的数学能力引发讨论。 “从技术人员…...

MacBook电脑远程连接Linux系统的服务器方法

一、问题简介 Windows 操作系统的电脑可使用Xshell等功能强大的远程连接软件。通过连接软件&#xff0c;用户可以在一台电脑上访问并控制另一台远程计算机。这对于远程技术支持、远程办公等场景非常有用。但是MacBook电脑的macOS无法使用Xshell。 在Mac上远程连接到Windows服…...

CSS-0_3 CSS和单位

文章目录 CSS的值和单位属性值长度单位CSS和绝对单位CSS和相对单位百分比em & rem视口 颜色单位 碎碎念 CSS的值和单位 我们知道&#xff0c;CSS是由属性和属性值所组成的表 随着CSS的发展&#xff0c;属性不说几千也有几百&#xff0c;我从来不支持去背诵所有的可能性。…...

【代码随想录|贪心算法 455. 分发饼干 376. 摆动序列 53. 最大子数组和】

代码随想录|贪心算法 455. 分发饼干 一、455. 分发饼干1.代码2.问题 二、376. 摆动序列1.代码 三、53. 最大子数组和1.代码 总结 python 一、455. 分发饼干 455. 分发饼干 1.代码 代码如下&#xff08;示例&#xff09;&#xff1a; class Solution:def findContentChildr…...

swift小知识点(二)

1、 Swift 枚举 Swift 中使用 enum 关键词来创建枚举并且把它们的整个定义放在一对大括号内&#xff1a; enum enumname {// 枚举定义放在这里 } 如下事例&#xff1a; // 定义枚举 enum DaysofaWeek {case Sundaycase Mondaycase TUESDAYcase WEDNESDAYcase THURSDAYcase…...

机器人产业发展格局多元化,创业公司突破瓶颈需多维施策

当前&#xff0c;机器人产业的发展格局呈现出多元化、快速增长和技术不断创新的特点。从全球视角来看&#xff0c;机器人市场持续增长&#xff0c;预计到2026年全球人形机器人市场规模将超过20亿美元&#xff0c;到2030年有望突破200亿美元&#xff0c;显示出巨大的市场潜力和发…...

接口测试JMeter-1.接口测试初识

第一章 接口测试初识 1. 接口测试理论基础 “接口测试”一个让人觉得非常高大上的名词&#xff0c;特别是对于刚入门的测试同学而言。随着测试技术不断的深化&#xff0c;“接口测试”出现在我们视野中的频次越来越高。那么接口测试到底是如何做的&#xff1f;接口测试的优势又…...

[米联客-安路飞龙DR1-FPSOC] FPGA基础篇连载-22 TPG图像测试数据发生器设计

软件版本&#xff1a;Anlogic -TD5.9.1-DR1_ES1.1 操作系统&#xff1a;WIN10 64bit 硬件平台&#xff1a;适用安路(Anlogic)FPGA 实验平台&#xff1a;米联客-MLK-L1-CZ06-DR1M90G开发板 板卡获取平台&#xff1a;https://milianke.tmall.com/ 登录“米联客”FPGA社区 ht…...

如何通过企业微信会话存档保护企业利益?

赵总: 张经理&#xff0c;最近行业内频发数据泄露事件&#xff0c;我们的客户资料和内部沟通记录安全吗&#xff1f; 张经理: 赵总&#xff0c;我们已经采取了一系列措施来加强数据安全。特别是针对企业微信的沟通记录&#xff0c;我们最近引入了安企神软件&#xff0c;它能很…...

git修改提交姓名

git config --global user.name “新用户名” git config --global user.email “新邮箱地址” 修改提交的用户名 git config --global user.name “yu***”...

5、在共享内存无指针编程:句柄HANDLE转换为指针

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 共享内存里面不能用指针&#…...

hive动态分区导致xceivercount超限,hdfs无法创建新连接

目录 一、事件复盘&#xff1a; 二、解决方案&#xff1a; 三、讨论 一、事件复盘&#xff1a; hdfs无法创建新的文件&#xff0c;xceivercount超过最大设置&#xff0c;平时每个datanode只有100个左右的连接&#xff0c;突然达到8000以上。 事故原因&#xff0c;跨多天的…...

如何识别Android init 中的缓慢操作

Android 14 开机时间优化措施汇总-CSDN博客 Android 14 开机时间优化措施-CSDN博客根据systrace报告优化系统时需要关注的指标和优化策略-CSDN博客Android系统上常见的性能优化工具-CSDN博客Android上如何使用perfetto分析systrace-CSDN博客Android系统设置kernel log level的…...

JVM:常用工具总结

文章目录 一、jstat工具 一、jstat工具 Jstat工具是JDK自带的一款监控工具&#xff0c;可以提供各种垃圾回收、类加载、编译信息等不同的数据。使用方法为&#xff1a;jstat -gc进程ID每次统计的时间间隔&#xff08;毫秒&#xff09;统计次数。 C代表Capacity容量&#xff0c…...

有源和无源

目录&#xff1a; 一、有源和无源 1、描述 2、电路实例 二、接点 1、干接点与湿接点 2、硬接点与软接点 一、有源与无源 1、概述 所谓有源就是指内部含有需要电源才能实现预期功能的元器件(或电路)&#xff1b; 所谓无源就是不需要电源供电&#xff0c;自身就有相应功能…...

ChatTTS角色系统:从技术原理到生产环境部署指南

在语音合成技术日益成熟的今天&#xff0c;多角色、高表现力的TTS系统已成为互动应用的关键组件。ChatTTS的角色系统允许在同一对话流中动态切换不同音色的语音输出&#xff0c;极大地提升了交互的自然度和沉浸感。然而&#xff0c;在实际生产部署中&#xff0c;开发者常面临一…...

STM32模拟UART实现技术详解

基于STM32的UART模拟实现技术解析1. UART通信基础原理1.1 异步串行通信基础通用异步收发器(UART)作为一种经典的串行通信方式&#xff0c;通过逐位传输实现数据通信。其核心优势在于传输线少、成本低&#xff0c;但相对并行通信速度较慢。异步通信模式下&#xff0c;收发双方的…...

认知雷达基础概念与核心理念总结

一、认知雷达的基础概念与核心理念认知雷达是一种全新的雷达技术范式&#xff0c;由 Haykin 和 Guerci 提出&#xff0c;借鉴了与知识相关的心理能力和认知过程的特性&#xff0c;核心理念是通过发射机与接收机之间持续且协调的反馈&#xff0c;让传感器算法根据实际运行环境和…...

从零开始:使用TypeScript快速构建浏览器RPG游戏的终极指南

从零开始&#xff1a;使用TypeScript快速构建浏览器RPG游戏的终极指南 【免费下载链接】RPG-JS Framework to create an RPG or MMORPG (with the same code) in the browser with Typescript 项目地址: https://gitcode.com/gh_mirrors/rp/RPG-JS 想要在浏览器中创建令…...

深入解析cosyvoice接口:从技术原理到高效集成实践

在智能语音交互领域&#xff0c;cosyvoice接口正扮演着越来越重要的角色。它让智能客服能够进行更自然流畅的多轮对话&#xff0c;为在线教育平台提供了实时语音评测与反馈的能力&#xff0c;同时也让各类智能硬件实现了精准的远场语音唤醒和指令识别。这些场景都离不开一个稳定…...

Web毕业设计效率提升指南:从脚手架选型到自动化部署的全流程优化

最近在帮学弟学妹们看毕业设计&#xff0c;发现大家普遍在项目初期浪费了大量时间。不是卡在环境配置&#xff0c;就是困在重复的脚手架搭建里&#xff0c;真正花在业务逻辑上的时间反而很少。今天就来聊聊&#xff0c;如何通过一套标准化的流程和工具&#xff0c;把 Web 毕业设…...

Python 3.14 JIT编译器深度调优实战(官方未公开的profile-driven优化链)

第一章&#xff1a;Python 3.14 JIT编译器演进与调优全景概览Python 3.14 引入了实验性但高度可配置的内置 JIT 编译器&#xff08;代号“Torchlight”&#xff09;&#xff0c;标志着 CPython 首次在标准发行版中集成生产就绪的即时编译能力。该 JIT 并非替代解释器&#xff0…...

嵌入式系统开发核心技术解析与实践

嵌入式系统开发核心技术专题1. 嵌入式开发基础体系1.1 C语言核心要点在嵌入式开发中&#xff0c;C语言作为最接近硬件的编程语言&#xff0c;需要掌握以下关键技术点&#xff1a;指针深度应用&#xff1a;包括函数指针、回调函数实现、内存操作等核心概念内存管理机制&#xff…...

豆包geo优化系统,源码开发搭建解析

豆包Geo优化系统解析豆包Geo优化系统通常指基于地理位置&#xff08;Geo&#xff09;数据的智能优化系统&#xff0c;可能涉及路径规划、区域划分、资源分配等场景。以下是其核心开发搭建要点&#xff1a;系统架构设计采用微服务架构&#xff0c;模块化设计便于扩展&#xff1a…...