当前位置:网站首页>读写关闭的channel是啥后果?
读写关闭的channel是啥后果?
2022-07-04 17:32:00 【小锟哥哥】
在 go 的面试中,最常问到的知识点无疑是 channel 了。
当 channel 关闭后再去读取数据会出现啥情况,最经常被问到。
一、正常的 channel
首先我们先来一段正常操作的代码:
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
for item := range ch {
fmt.Println(item)
}
这段代码应该非常熟悉,这样写是否有问题呢?
执行后的结果:
$ go run n.go
1
2
3
fatal error: all goroutines are asleep - deadlock!
如果一个 channel 不在某个协程里面关闭的话,我们的 for range 就会报死锁的错误。
二、关闭后再读取
1、使用 for range 读取关闭后的 channel
现在我们在 for range 之前关闭下这个 channel,看会出现啥情况:
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch)
// 如果不关闭会报死锁 fatal error: all goroutines are asleep - deadlock!
for item := range ch {
fmt.Println(item)
}
这样写代码会出现啥问题呢?
$ go run n.go
1
2
3
啥错也没有,正常的读取。
2、直接独立取值
下面我们换直接独立取值的方式:
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch)
item, state := <-ch // state 为是否读到有值
fmt.Println(item, state)
state 会返回是否取到了值,这段代码的执行结果是取到第一个值:
$ go run n.go
1 true
如果我们反复读取呢?
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch)
<-ch
<-ch
<-ch
item, state := <-ch // state 为是否读到有值
fmt.Println(item, state) //全部读完值之后,再读也不会报错,只会取到零值
我前面读取 3 次,把里面的数据读取完毕后,再读取得到就是零值了。
$ go run n.go
0 false
所以结论是:如果 channel 有元素还未读,会正确读出来,哪怕他已经关闭了。
三、往里面写值呢?
最后一起来看下,当 channel 关闭后,往里面写值会怎样?
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch)
ch <- 4
这段代码执行后的结果:
$ go run n.go
panic: send on closed channel
会报 panic,具体原因我们可以看 go 的源码,路径为:src/runtime/chan.go

边栏推荐
- Rookie post station management system based on C language
- Behind the ultra clear image quality of NBA Live Broadcast: an in-depth interpretation of Alibaba cloud video cloud "narrowband HD 2.0" technology
- Li Kou brush question diary /day1/2022.6.23
- VMware Tools和open-vm-tools的安装与使用:解决虚拟机不全屏和无法传输文件的问题
- Reptile elementary learning
- Nebula Importer 数据导入实践
- 【OpenCV入门到精通之九】OpenCV之视频截取、图片与视频互转
- Nature microbiology | viral genomes in six deep-sea sediments that can infect Archaea asgardii
- Microservice architecture debate between radical technologists vs Project conservatives
- 基于C语言的菜鸟驿站管理系统
猜你喜欢

Scala基础教程--15--递归

Machine learning concept drift detection method (Apria)

一种将Tree-LSTM的强化学习用于连接顺序选择的方法

力扣刷題日記/day6/6.28

输入的查询SQL语句,是如何执行的?

MXNet对GoogLeNet的实现(并行连结网络)

力扣刷题日记/day8/7.1
![[go language question brushing chapter] go conclusion chapter | introduction to functions, structures, interfaces, and errors](/img/7a/16b481753d7d57f50dc8787eec8a1a.png)
[go language question brushing chapter] go conclusion chapter | introduction to functions, structures, interfaces, and errors

VMware Tools和open-vm-tools的安装与使用:解决虚拟机不全屏和无法传输文件的问题

激进技术派 vs 项目保守派的微服务架构之争
随机推荐
Scala基础教程--15--递归
字节跳动Dev Better技术沙龙成功举办,携手华泰分享Web研发效能提升经验
File processing examples of fopen, FREAD, fwrite, fseek
IBM WebSphere MQ检索邮件
启牛开的证券账户安全吗?
中国农科院基因组所汪鸿儒课题组诚邀加入
爬虫(6) - 网页数据解析(2) | BeautifulSoup4在爬虫中的使用
物联网应用技术的就业前景和现状
Scala basic tutorial -- 19 -- actor
fopen、fread、fwrite、fseek 的文件处理示例
Journal des problèmes de brosse à boutons de force / day6 / 6.28
输入的查询SQL语句,是如何执行的?
Scala basic tutorial -- 14 -- implicit conversion
Nebula Importer 数据导入实践
建立自己的网站(15)
Wanghongru research group of Institute of genomics, Chinese Academy of Agricultural Sciences is cordially invited to join
[210] usage of PHP delimiter
Esp32-c3 introductory tutorial questions ⑫ - undefined reference to ROM_ temp_ to_ power, in function phy_ get_ romfunc_ addr
力扣刷题日记/day7/2022.6.29
VMware Tools和open-vm-tools的安装与使用:解决虚拟机不全屏和无法传输文件的问题