GO学习之 通道(nil Channel妙用)

GO系列

1、GO学习之Hello World
2、GO学习之入门语法
3、GO学习之切片操作
4、GO学习之 Map 操作
5、GO学习之 结构体 操作
6、GO学习之 通道(Channel)
7、GO学习之 多线程(goroutine)
8、GO学习之 函数(Function)
9、GO学习之 接口(Interface)
10、GO学习之 网络通信(Net/Http)
11、GO学习之 微框架(Gin)
12、GO学习之 数据库(mysql)
13、GO学习之 数据库(Redis)
14、GO学习之 搜索引擎(ElasticSearch)
15、GO学习之 消息队列(Kafka)
16、GO学习之 远程过程调用(RPC)
17、GO学习之 goroutine的调度原理
18、GO学习之 通道(nil Channel妙用)

文章目录

  • GO系列
  • 前言
  • 一、nil channel读写阻塞
  • 二、nil channel 妙用
    • 2.1 一个普通示例
    • 2.2 示例运行分析
    • 2.3 如何妙用 nil channel
  • 三、总结

前言

按照公司目前的任务,go 学习是必经之路了,虽然行业卷,不过技多不压身,依旧努力!!!
在《GO学习之 通道(Channel)》篇中,主要对 Channel 做了简介和用法,主要包含 无缓存通道、有缓存通道 和 单向通道 等,此篇补充一个 nil channel的用法,
看 nil channel 的妙用。

—— 本文内容借鉴《Go语音精进之路》一书。
Go语言精进之路

一、nil channel读写阻塞

对于没有初始化的 channel (nil channel) 进行读写操作会发生阻塞,比如:

package mainfunc main() {var c chan intc <- 1
}

或者

package mainfunc main() {var c chan int<-c
}

无论是上哪段代码,运行都会得到错误的结果, main goroutine 被阻塞在 channel 上,导致 Go 运行时认为出现 deadlock状态并抛出 panic。

PS D:\workspaceGo\src\channel> go run .\nilChannel.go
fatal error: all goroutines are asleep - deadlock!goroutine 1 [chan send (nil chan)]:
main.main()D:/workspaceGo/src/channel/nilChannel.go:5 +0x25
exit status 2

二、nil channel 妙用

2.1 一个普通示例

一般我们在程序中习惯用 channel、goroutine 和 select 来搭配运行,例如:

下面的示例代码中,声明了 c1 c2 两个 channel,并且启动两个 goroutine 向 c1 c2 中延时后添加值,在 for 循环中用 select case 获取到 c1 c2 中的值。

package mainimport ("fmt""time"
)func main() {// 声明 c1 c2 两个通道,并且用 make 函数实例化c1, c2 := make(chan int), make(chan int)go func() {time.Sleep(time.Second * 5)c1 <- 5close(c1)}()go func() {time.Sleep(time.Second * 7)c2 <- 7close(c2)}()var ok1, ok2 boolfor {select {case x := <-c1:ok1 = truefmt.Println(x)case x := <-c2:ok2 = truefmt.Println(x)}if ok1 && ok2 {break}}fmt.Println("program end!")
}

在上面的示例中,我们期望程序在接受完 c1 和 c2 两个 channel 上的数据后就退出,但实际运行结果如下:

PS D:\workspaceGo\src\channel> go run .\nilChannel.go
5
0
0
0
...
7
program end!

期望是程序在输出 5 和 7 之后退出,但实际结果中,输出完 5 之后,程序多输出了几个 0 之后才退出。

2.2 示例运行分析

  1. 程序开始运行,前 5s,select 一直处于阻塞状态。
  2. 第 5s,c1 返回一个 5 后被关闭了,select 语句的 case x := <- c1 分支被执行,程序输出 5,则 for 循环开始新的 select 执行。
  3. c1 已经被关闭,由于从一个已经的关闭的 channel 接受数据将永远不会被阻塞,所以新一轮 select 又将 case x := <- c1 被执行,由于 c1 是关闭状态的,从这个 channel 获取到对于类型的零值,即 0,于是程序输出了 0。所以在 for 循环里面,则一直输出 0 值。
  4. 2s 后,c2 被写入一个数值 7,此时在某一轮循环中,select 则选出 case x: <- c2 并执行。程序输出 7 之后满足条件退出循环,程序终止。

2.3 如何妙用 nil channel

nil channel并非一无是处,nil channel 只要用对了地方,用对了时候,就可以达到事半功倍的效果,将上面的实例程序做了改进,示例代码如下:

package mainimport ("fmt""time"
)func main() {// 声明 c1 c2 两个通道,并且用 make 函数实例化c1, c2 := make(chan int), make(chan int)go func() {time.Sleep(time.Second * 5)c1 <- 5close(c1)}()go func() {time.Sleep(time.Second * 7)c2 <- 7close(c2)}()for {select {case x, ok := <-c1://判断是否获取成功,不成功则把 c1 置为 nilif !ok {c1 = nil} else {fmt.Println(x)}case x, ok := <-c2://判断是否获取成功,不成功则把 c2 置为 nilif !ok {c2 = nil} else {fmt.Println(x)}}if c1 == nil && c2 == nil {break}}fmt.Println("program end!")
}

程序的关键变化在判断 c1 或者 c2被关闭后,显示地把 c1 c2 两个 channel 置为了 nil。
有什么效果呢? 因为 对一个 nil channel 执行获取操作,该操作会被阻塞 ,因此已经被置为 nil 的 c1 c2 再也不会被 select 选中执行了。
运行结果:

PS D:\workspaceGo\src\channel> go run .\nilChannel.go 
5
7
program end!

三、总结

此篇主要在特殊场景下,用了 nil channel 来巧妙的终结了 for select 程序,避免了运行结果的错误,因为 对一个 nil channel 执行获取操作,该操作会被阻塞,但对 一个一个关闭了的 channel 执行获取操作,则会得到 0值

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mac电脑Android Studio和VS Code配置Flutter开发环境(图文超详细)

一、安装Android Studio 官网地址&#xff1a; https://developer.android.google.cn/ 历史版本下载地址&#xff1a; https://developer.android.com/studio/archive?hlzh-cn 二、安装Xcode 到App Store下载安装最新版本&#xff0c;如果MacOS更新不到13.0以上就无法安装…

Go-Python-Java-C-LeetCode高分解法-第十二周合集

前言 本题解Go语言部分基于 LeetCode-Go 其他部分基于本人实践学习 个人题解GitHub连接&#xff1a;LeetCode-Go-Python-Java-C 欢迎订阅CSDN专栏&#xff0c;每日一题&#xff0c;和博主一起进步 LeetCode专栏 我搜集到了50道精选题&#xff0c;适合速成概览大部分常用算法 突…

消息中间件——RabbitMQ(一)Windows/Linux环境搭建(完整版)

前言 最近在学习消息中间件——RabbitMQ&#xff0c;打算把这个学习过程记录下来。此章主要介绍环境搭建。此次主要是单机搭建&#xff08;条件有限&#xff09;&#xff0c;包括在Windows、Linux环境下的搭建&#xff0c;以及RabbitMQ的监控平台搭建。 环境准备 在搭建Rabb…

机器人的触发条件有什么区别,如何巧妙的使用

简介​ 维格机器人触发条件,分为3个,分别是: 有新表单提交时、有记录满足条件时、有新的记录创建时 。 看似3个,其实是能够满足我们非常多的使用场景。 本篇将先介绍3个条件的触发条件,然后再列举一些复杂的触发条件如何用现有的触发条件来满足 注意: 维格机器人所有的…

Linux(Centos7)防火墙端口操作记录

1、nginx -t #Nginx配置文件检查 上述截图代表检查没问题 上述截图检查配置文件配置错误&#xff0c;并提示错误文件位置 2、systemctl restart nginx #重启Nginx 重启Nginx失败 3、systemctl status nginx.service #查看Nginx服务状态 80端口被占导致服务启动失败 4、n…

除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂…

代码随想录打卡第五十五天|● 300.最长递增子序列 ● 674. 最长连续递增序列 ● 718. 最长重复子数组

300.最长递增子序列 **题目&#xff1a;**给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组 [0…

深度学习| U-Net网络

U-Net网络 基础知识和CNN的关系反卷积ReLU激活函数 U-Net入门U-Net网络结构图为什么需要跳跃连接U-Net的输入U-Net的应用 基础知识 理解U-Net网络结构需要相关知识点。 和CNN的关系 U-Net也是CNN&#xff08;Convolutional Neural Network&#xff0c;卷积神经网络&#xff…

Flutter PopupMenuButton下拉菜单

下拉菜单是移动应用交互中一种常见的交互方式,可以使用下拉列表来展示多个内容标签,实现页面引导的作用。在Flutter开发中,实现下拉弹框主要有两种方式,一种是继承Dialog组件使用自定义布局的方式实现,另一种则是使用官方的PopupMenuButton组件进行实现。 如果没有特殊的…

Android任务栈和启动模式

Andrcid中的任务栈是一种用来存放Activity实倒的容器。任务最大的特点就是先进后出&#xff0c;它主要有两个基本操作&#xff0c;分别是压栈和出栈。通常Andaid应用程序都有一个任务栈&#xff0c;每打开一个Activity时&#xff0c;该Activity就会被压入任务栈。每销毁一个Act…

Unity Animator cpu性能测试

测试案例&#xff1a; 场景中共有4000个物体&#xff0c;挂在40个animtor 上&#xff0c;每个Animator控制100个物体的动画。 使用工具&#xff1a; Unity Profiler. Unity 版本&#xff1a; unity 2019.4.40f1 测试环境&#xff1a; 手机 测试过程&#xff1a; 没有挂…

VNC图形化远程连接Ubuntu服务器

我的Ubuntu版本22.04.3&#xff0c;带有gnome图形桌面。配置过程参考了几篇博客&#xff0c;大致流程如下。因为是配置完之后才整理的流程&#xff0c;可能有疏漏。 Ubuntu服务器上的配置 1.先在服务器上下载vnc server&#xff08;任何一种版本均可&#xff09; vncserver有…

VS Code2023安装教程(最新最详细教程)附网盘资源

目录 一.简介 二.安装步骤 三.VS Code 使用技巧 网盘资源见文末 一.简介 VS Code是一个由微软开发的跨平台的轻量级集成开发环境&#xff08;IDE&#xff09;&#xff0c;被广泛用于编写各种编程语言的代码。它支持多种编程语言&#xff0c;并且可以通过插件扩展功能。 以…

Undefined reference错误处理及Linux设置动态链接库so的默认搜索路径

文章目录 1 问题的提出2 问题的分析3 问题的解决3.1 Windows的VS修改配置属性3.2 Linux系统里添加搜索路径json在/usr/llib目录中libcryto.so在/usr/lib64文件夹中 Linux设置动态链接库so的默认搜索路径方法一&#xff1a;修改 ld.so.conf 文件方法二&#xff1a;修改环境变量方…

matlab 布尔莎七参数坐标转换模型

目录 一、算法原理二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。爬虫自重,把自己当个人。 一、算法原理 算法原理与实现代码已在免费文章:布尔莎七参数坐标转换模型一文中给出,不想看付费文章直接跳转即可。 二、代码实现 clc; clear; close all; %% --

08 _ 栈:如何实现浏览器的前进和后退功能?

浏览器的前进、后退功能,我想你肯定很熟悉吧? 当你依次访问完一串页面a-b-c之后,点击浏览器的后退按钮,就可以查看之前浏览过的页面b和a。当你后退到页面a,点击前进按钮,就可以重新查看页面b和c。但是,如果你后退到页面b后,点击了新的页面d,那就无法再通过前进、后退…

软考系统架构师知识点集锦十:计算机网络、数学与经济管理、知识产权与标准化

一、计算机网络 1.1、考情分析 2.1 TCP/IP协议簇 2.1.1常见协议及功能 网际层是整个TCP/IP体系结构的关键部分,其功能是使主机可以把分组发往任何网络并使分组独立地传向目标。 POP3: 110 端口&#xff0c;邮件收取SMTP: 25 端口&#xff0c;邮件发送FTP: 20数据端口/21控制…

nextcloud+onlyoffice环境搭建(在线 or 离线)

1.安装 MySQL&#xff08;有MySQL就可以不装&#xff09; docker run -itd --name mysql8.0 -p 3306:3306 -e MYSQL_ROOT_PASSWORDroot --restartalways -e TZ"Asia/Shanghai" -v /home/docker/workspace/mysql:/var/lib/mysql mysql:latest --lower_case_table_na…

正点原子嵌入式linux驱动开发——外置RTC芯片PCF8563

上一章学习了STM32MP1内置RTC外设&#xff0c;了解了Linux系统下RTC驱动框架。一般的应用场合使用SOC内置的RTC就可以了&#xff0c;而且成本也低&#xff0c;但是在一些对于时间精度要求比较高的场合&#xff0c;SOC内置的RTC就不适用了。这个时候需要根据自己的应用要求选择合…

吉他、班卓琴和贝斯吉他降分器:Arobas Music Guitar 8.1.1

Arobas Music Guitar 是一款专业的吉他、班卓琴和贝斯吉他降分器。在熟练的手中&#xff0c;它不仅可以让您创作&#xff0c;还可以编辑、聆听和录制&#xff0c;以及导入和导出乐谱。如果有人感兴趣的话&#xff0c;录音是在八个轨道上进行的&#xff0c;你可以为每个轨道单独…