Channel 使用事项和注意细节

(1)channel 可以声明为只读,或者只写性质
(2)channel 只读和只写的最佳实践案例

在默认情况下,管道是双向管道,即可读可写。

var ch chan int

func main() {
	//声明为只写管道
	var chan1 chan<- int
	chan1 = make(chan int, 3)
	fmt.Println(chan1)

	//声明为只读
	var chan2 <-chan int
	chan2 = make(chan int, 3)
	fmt.Println(chan2)
}

下面是只读,只写管道,可以有效的预防我们误操作。相当于将可读可写管道将只读的功能封装起来了,不给你使用,但是类型依然是chan int类型。

 

 

 select + channel  示例


使用select可以解决从管道取数据的阻塞问题【案例演示】

假设要从网上下载一个文件,我启动了 3 个 goroutine 进行下载,并把结果发送到 3 个 channel 中。其中,哪个先下载好,就会使用哪个 channel 的结果。

在这种情况下,如果我们尝试获取第一个 channel 的结果,程序就会被阻塞,无法获取剩下两个 channel 的结果,也无法判断哪个先下载好。这个时候就需要用到多路复用操作了,在 Go 语言中,通过 select 语句可以实现多路复用,其语句格式如下:

select {
case i1 = <-c1:
     //todo
case c2 <- i2:
	//todo
default:
	// default todo
}

整体结构和 switch 非常像,都有 case 和 default,只不过 select 的 case 是一个个可以操作的 channel。

小提示:多路复用可以简单地理解为,N 个 channel 中,任意一个 channel 有数据产生,select 都可以监听到,然后执行相应的分支,接收数据并处理。

有了 select 语句,就可以实现下载的例子了,如下面的代码所示:

func main() {

   //声明三个存放结果的channel
   firstCh := make(chan string)
   secondCh := make(chan string)
   threeCh := make(chan string)

   //同时开启3个goroutine下载
   go func() {
      firstCh <- downloadFile("firstCh")
   }()

   go func() {
      secondCh <- downloadFile("secondCh")
   }()

   go func() {
      threeCh <- downloadFile("threeCh")
   }()

   //开始select多路复用,哪个channel能获取到值,就说明哪个最先下载好,就用哪个。

   select {
       case filePath := <-firstCh:
       fmt.Println(filePath)

       case filePath := <-secondCh:
       fmt.Println(filePath)

       case filePath := <-threeCh:
       fmt.Println(filePath)
   }
}

func downloadFile(chanName string) string {
   //模拟下载文件,可以自己随机time.Sleep点时间试试
   time.Sleep(time.Second)
   return chanName+":filePath"
}

如果这些 case 中有一个可以执行,select 语句会选择该 case 执行,如果同时有多个 case 可以被执行,则随机选择一个,这样每个 case 都有平等的被执行的机会。如果一个 select 没有任何 case,那么它会一直等待下去。

---------------------------------------------------------------------------------------------------------------------------

要从管道当中读取数据需要close这个管道,不去close这个管道去遍历的时候,管道会阻塞,如果阻塞在main协程里面会发生死锁。

package main

import (
	"fmt"
	"time"
)

func main() {
	//使用select可以解决从管道当中读取数据阻塞的问题

	//1.定义一个管道 10个数据int
	initChan := make(chan int, 10)
	for i := 0; i < 5; i++ {
		initChan <- i
	}
	//2.定义一个管道 5个数据string
	stringChan := make(chan string, 5)
	for i := 0; i < 5; i++ {
		stringChan <- "hello" + fmt.Sprintf("%d", i)
	}

	//传统的方法在遍历管道的时候如果不关闭会阻塞导致死锁
	//在实际开发过程中,可能无法确定什么时候关闭该管道
	//可以使用select的方式可以解决

	for {
		select {
		//如果管道一直没有关闭,也不会一直阻塞在这里导致死锁
		// 它会自动的到下一个case匹配,不依赖关闭
		case v := <-initChan:
			time.Sleep(time.Second * 1)
			fmt.Printf("从intchan读取了数据%d\n", v)
		case v := <-stringChan:
			time.Sleep(time.Second * 1)
			fmt.Printf("从stringChan读取了数据%s\n", v)
		default:
			time.Sleep(time.Second * 1)
			fmt.Println("都取不到了,不玩了,这里可以加入业务逻辑")
		}
	}
}



从intchan读取了数据0
从intchan读取了数据1
从intchan读取了数据2
从intchan读取了数据3
从intchan读取了数据4
从stringChan读取了数据hello0
从stringChan读取了数据hello1
从stringChan读取了数据hello2
从stringChan读取了数据hello3
从stringChan读取了数据hello4
都取不到了,不玩了,这里可以加入业务逻辑
都取不到了,不玩了,这里可以加入业务逻辑
都取不到了,不玩了,这里可以加入业务逻辑
都取不到了,不玩了,这里可以加入业务逻辑

如果是在函数里面,直接使用return,那么就直接退出协程的函数。


4)goroutine中使用recover,解决协程中出现panic,导致程序崩溃问题.【案例演示】
说明:如果我们起了一个协程,但是这个协程出现了panic,如果我们没有捕获这个panic,就会造成整个程序崩溃,这时我们可以在goroutine中使用recover来捕获panic,进行处理,这样即使这个协程发生的问题,但是主var mapl map[string]string线程仍然不受影响,可以继续执行。map1["nol”]="tom"
 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

系统编程--常用命令

这里写目录标题 常用命令tab补齐获取历史命令快捷键相对路径和绝对路径ls补充详细区分文件对自己自身列-l递归ls which命令 系统目录介绍内容补充上一级目录运行一个可执行文件&#xff08;运行一个程序&#xff09; 一级目录二级目录二级目录二级目录 一级目录二级目录二级目录…

linux基于用户身份对资源访问进行控制的解析及过程

linux中用户分为三类 1.超级用户&#xff08;root&#xff09; 拥有至高无上的权限 2.普通用户 人为创建、权限小&#xff0c;权限受到控制 3.程序用户 运行程序的用户&#xff0c;不是给人使用的&#xff0c;给程序使用的&#xff0c;一般不给登录&#xff01; 组账…

第2课 使用FFmpeg读取rtmp流并用openCV显示视频

本课对应源文件下载链接&#xff1a; https://download.csdn.net/download/XiBuQiuChong/88680079 这节课我们开始利用ffmpeg和opencv来实现一个rtmp播放器。播放器的最基本功能其实就两个:显示画面和播放声音。在实现这两个功能前&#xff0c;我们需要先用ffmpeg连接到rtmp服…

解决IDEA 不能正确识别系统环境变量的问题

问题描述 本人laptop 上的是设置了GOOGLE_APPLICATION_CREDENTIALS 这个环境变量的&#xff0c; 正常java or python 的程序能基于这个环境变量使用 某个gcp service account 去访问GCP的资源 [gatemanmanjaro-x13 ~]$ env | grep -i google GOOGLE_APPLICATION_CREDENTIALS/…

ubuntu 安装apisix -亲测可用

官方未提供在ubuntu系统中安装apisix的方式&#xff0c;似乎只能通过源码方式安装&#xff0c;但是并不推荐&#xff0c;非常容易失败&#xff0c; 具体操作方式如下&#xff1a; ubuntu和Debian其实类似的&#xff0c;可使用DEB方式安装&#xff0c;如下截图 注意&#xff1…

年度总结|存储随笔2023年度最受欢迎文章榜单TOP15-part2

TOP11&#xff1a;PCIe在狂飙&#xff0c;SAS存储之路还有多远&#xff1f; 随着科技的飞速发展&#xff0c;固态硬盘&#xff08;SSD&#xff09;已经成为现代计算机系统中不可或缺的一部分。它以其出色的性能和可靠性&#xff0c;改变了我们对于存储设备的期待。当前业内SSD广…

通用定时器PWM波输出原理

1通用PWM波输出原理 总结&#xff1a;PWM波周期或频率由ARR决定&#xff0c;PWM波占空比由CCRx决定 1通用PWM模式 1.1PWM模式1 PWM模式1&#xff1a; 递增&#xff1a;CNT < CCRx&#xff0c;输出有效电平1 CNT > CCRx&#xff0c;输出无效电平0 递减&#xff1a;CNT …

Python面向对象编程 —— 类和异常处理

​ &#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 &#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 目录 1. 类 1.1 类的定义 1.2 类变量和实例变量 1.3 类的继承 2. 异常处理 2.1类型异常 2.…

fiddler菜单汉化补丁

【Fiddler汉化补丁下载地址】 一、手机应用市场下载“头条搜索极速版”app 二、头条搜索极速版中搜索“葫芦娃指南”获取 三、汉化过程完整过程 1、安装Fiddler英文版 2、比如我将Fiddler安装在&#xff1a;D:\Programs\Fiddler 3、将【fiddler汉化】文件夹中的FiddlerT…

2024年【茶艺师(初级)】考试技巧及茶艺师(初级)试题及解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 茶艺师&#xff08;初级&#xff09;考试技巧是安全生产模拟考试一点通生成的&#xff0c;茶艺师&#xff08;初级&#xff09;证模拟考试题库是根据茶艺师&#xff08;初级&#xff09;最新版教材汇编出茶艺师&#…

【基于VirtualBox及openEuler20.03 TLS SP1编译openGauss2.1.0源码】

【openEuler 20.03 TLS编译openGauss2.1.0源码】 一、安装环境二、安装步骤 一、安装环境 项目Value虚拟机virtualbox操作系统openEuler 20.03 TLSopenGauss2.1.0openGauss-third_party2.1.0 二、安装步骤 以下操作需要在root用户下执行 编辑/etc/selinux/config vim /etc/s…

分享一个学习Typescript最全的Github网站

一个专注研究Typescript的网站&#xff0c;&#x1f396;&#x1f396;&#x1f396;在这里你可以全面深入学习Typescript相关知识,通过动画方式讲解TS&#xff0c;还有很多常见问题解答。你还可以挑战相应的题目&#xff0c;快来学习吧 我就懒一点&#xff0c;直接原滋原味的…

跟踪SEO性能

他们说&#xff0c;如果你能衡量一些东西&#xff0c;你就可以改进它。 在SEO中&#xff0c;也不例外。专业的SEO跟踪从排名和转化到丢失链接等的所有内容&#xff0c;以帮助证明SEO的价值。衡量你的工作和持续改进的影响&#xff0c;对于你的SEO成功、客户保留和感知价值至关…

工智能基础知识总结--什么是CNN

什么是CNN 卷积神经网络(Convolutional Neural Networks, CNN)是一类包含卷积计算且具有深度结构的前馈神经网络(Feedforward Neural Networks),是深度学习(deep learning)的代表算法之一。CNN最常用于CV领域,但是在NLP等其他领域也有应用,如用于文本分类的TextCNN。 …

搞知识竞赛活动要做哪些准备工作

举办知识竞赛&#xff0c;大量的精力和时间投入是在筹划准备阶段。诸如竞赛的策划布置、题库的设计建立、参赛人员的复习准备、竞赛器具的购置、赛场的布置安装、对各环节的督促检验等一系列工作&#xff0c;都是在此期间进行和完成的。无论哪一环节出现疏漏偏差&#xff0c;都…

如何通过易舟云财务软件,查看账簿的总账?

如何通过易舟云财务软件&#xff0c;查看账簿的总账&#xff1f; 前言财务软件操作步骤 前言 总账是会计中的一个重要概念&#xff0c;是指记录一个企业在一定时期内所有经济业务活动的账簿。总账记录了企业的资产、负债、所有者权益、收入和费用等各项会计科目的变动情况。 …

MySQL多表查询的方法(含例子)

我们查两张及以上表的时候&#xff0c;普通的查询语法(select * from 表名&#xff09;不能发挥作用。下面我演示两张表和三张表的查询方法。 前提&#xff1a; 如图存在三张表a&#xff0c;b&#xff0c;c&#xff1a;a表是学生基础信息&#xff0c;b表是教师学科信息&#…

【Python特征工程系列】教你利用XGBoost模型分析特征重要性(源码)

这是Python特征工程系列原创文章&#xff0c;我的第186篇原创文章。 一、问题 应用背景介绍&#xff1a; 如果有一个包含数十个甚至数百个特征的数据集&#xff0c;每个特征都可能对你的机器学习模型的性能有所贡献。但是并不是所有的特征都是一样的。有些可能是冗余的…

LDO线性稳压器与开关电源的原理

线性稳压器LDO典型代表&#xff1a;LM7805 ,AMS1117&#xff0c;还有一下性能比较好的LDO&#xff1a; 开关稳压器典型代表&#xff1a;LM2596&#xff0c;MP1584,TPS5430&#xff0c;MP2315S LDO靠发热分散能量&#xff0c;纹波较小一般在30mv以下&#xff1b;DCDC通过开关开断…