前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >读写关闭的 channel 有啥后果?

读写关闭的 channel 有啥后果?

作者头像
小锟哥哥
发布2022-12-05 14:03:32
8590
发布2022-12-05 14:03:32
举报
文章被收录于专栏:GoLang全栈

在 go 的面试中,最常问到的知识点无疑是 channel 了。

当 channel 关闭后再去读取数据会出现啥情况,最经常被问到。

一、正常的 channel

首先我们先来一段正常操作的代码:

代码语言:javascript
复制
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3

for item := range ch {
 fmt.Println(item)
}

这段代码应该非常熟悉,这样写是否有问题呢?

执行后的结果:

代码语言:javascript
复制
$ go run n.go 
1
2
3
fatal error: all goroutines are asleep - deadlock!

如果一个 channel 不在某个协程里面关闭的话,我们的 for range 就会报死锁的错误。

二、关闭后再读取

1、使用 for range 读取关闭后的 channel

现在我们在 for range 之前关闭下这个 channel,看会出现啥情况:

代码语言:javascript
复制
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)
 }

这样写代码会出现啥问题呢?

代码语言:javascript
复制
$ go run n.go 
1
2
3

啥错也没有,正常的读取。

2、直接独立取值

下面我们换直接独立取值的方式:

代码语言:javascript
复制
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch)
item, state := <-ch      // state 为是否读到有值
fmt.Println(item, state)

state 会返回是否取到了值,这段代码的执行结果是取到第一个值:

代码语言:javascript
复制
$ go run n.go 
1 true

如果我们反复读取呢?

代码语言:javascript
复制
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 次,把里面的数据读取完毕后,再读取得到就是零值了。

代码语言:javascript
复制
$ go run n.go 
0 false

所以结论是:如果 channel 有元素还未读,会正确读出来,哪怕他已经关闭了。

三、往里面写值呢?

最后一起来看下,当 channel 关闭后,往里面写值会怎样?

代码语言:javascript
复制
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch)
ch <- 4

这段代码执行后的结果:

代码语言:javascript
复制
$ go run n.go 
panic: send on closed channel

会报 panic,具体原因我们可以看 go 的源码,路径为:src/runtime/chan.go

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-07-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 GoLang全栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、正常的 channel
  • 二、关闭后再读取
    • 1、使用 for range 读取关闭后的 channel
      • 2、直接独立取值
      • 三、往里面写值呢?
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档