登录
首页 >  Golang >  Go问答

go通道channel使用for-range造成死锁,而使用for计数器迭代却不会?

来源:SegmentFault

时间:2023-01-08 11:46:48 136浏览 收藏

知识点掌握了,还需要不断练习才能熟练运用。下面golang学习网给大家带来一个Golang开发实战,手把手教大家学习《go通道channel使用for-range造成死锁,而使用for计数器迭代却不会?》,在实现功能的过程中也带大家重新温习相关知识点,温故而知新,回头看看说不定又有不一样的感悟!

问题内容

使用以下代码可以正常执行

func main() {
    count := 10
    ch := generate(count)
    for i := 0; i 

但是换成以下代码,却会提示 fatal error: all goroutines are asleep - deadlock!

func main() {
    count := 10
    ch := generate(count)
    for v := range ch {
        fmt.Println(v)
    }
}
func generate(count int) 

想知道使用上述代码时,for-range循环接收造成死锁的原因是什么?这两者的区别是什么?

正确答案

RangeClause

For channels, the iteration values produced are the successive values sent on the channel until the channel is closed. If the channel is nil, the range expression blocks forever.

只有 channel 被关掉才能结束。

你说的这个我也在《The Way to Go》 也有看到,但是不理解“从指定通道中读取数据直到通道关闭”中的直到通道关闭是指什么。channel关闭是指执行close(ch)方法吗?但返回的是一个只读channel,不可以关闭。

是的,close(ch)。关闭之后,这个 channel 无法发送(会 panic),也无法接受(缓存用光后,直接返回 zero value)。

在generate返回ch前关闭,虽然没有报死锁,但是没有打印任何数据。

这个估计 go routine 启动之前 ch 就关闭了, range 一个数据都读不到直接退出,main 结束,程序退出。

程序如果没有很快退出,go routine 执行了,向关闭的 ch 写数据会 panic 。

而且,还是用for-range读取通道数据,但是用一个新goroutine却不会发生死锁

   go func() {
       for v := range ch {
           fmt.Println(v)
       }
   }()

看一眼你的错误:

fatal error: all goroutines are asleep - deadlock!

只有所有的 go routine 全部锁住才会报死锁。但是,你再起一个新的 go routine ,你的发送跟接受的 go routine 都锁住了,但是 main 所在的 go routine 并没有被锁住,所以不会报此错误。

理论要掌握,实操不能落!以上关于《go通道channel使用for-range造成死锁,而使用for计数器迭代却不会?》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!

声明:本文转载于:SegmentFault 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>
评论列表