为了账号安全,请及时绑定邮箱和手机立即绑定

高浪为什么不能将值传递到主线程上的通道

高浪为什么不能将值传递到主线程上的通道

Go
偶然的你 2022-09-26 15:21:00
案例1package mainfunc main()  {    dogChan := make(chan int)    dogChan <- 1}fatal error: all goroutines are asleep - deadlock!goroutine 1 [chan send]:main.main()    /Users/xuzhongwei/Source/awesomeProject/main.go:5 +0x50案例2package mainfunc main()  {    dogChan := make(chan int)    go func(ch chan int) {            }(dogChan)    dogChan <- 1}fatal error: all goroutines are asleep - deadlock!goroutine 1 [chan send]:main.main()    /Users/xuzhongwei/Source/awesomeProject/main.go:9 +0x72案例3package mainfunc main()  {    dogChan := make(chan int)    go func(ch chan int) {        <- ch    }(dogChan)    dogChan <- 1}案例4package mainfunc main()  {    dogChan := make(chan int)        go func(ch chan int) {        <- ch    }(dogChan)    dogChan <- 1    dogChan <- 2}fatal error: all goroutines are asleep - deadlock!goroutine 1 [chan send]:main.main()    /Users/xuzhongwei/Source/awesomeProject/main.go:10 +0x90案例5package mainfunc main()  {    dogChan := make(chan int)    go func(ch chan int) {        for {            select {                case <- ch:            }        }    }(dogChan)    dogChan <- 1    dogChan <- 2    dogChan <- 3    dogChan <- 4    dogChan <- 5}谁能告诉我为什么案例1,案例2有错误,而案例3是好的?在案例1中,我的猜测是dogChan不用于戈鲁丁,所以它被处理成关闭。在案例2中,我的猜测是,虽然dogChan在戈鲁丁中传递,但它没有用于戈鲁丁,所以它被处理为封闭谁能告诉我为什么案例4有错误,而案例5是好的?
查看完整描述

2 回答

?
PIPIONE

TA贡献1829条经验 获得超9个赞

你认为为什么会发生这种情况?通道应充当发送方和接收方之间的同步原语。您有一个发件人在频道上发送,但没有一个在频道上接收。如果没有接收戈鲁丁或对戈鲁丁的接收操作,发送方只需阻止(作为无缓冲通道)case1case2dogChan

在 上出现同样的问题,您在信道上有两个发送,但在戈鲁廷上有一个接收。将永远阻止。在 中,如果您打算从通道中读取,只需使用循环来迭代通过通道发送的连续值。case4dogChan <- 2case5range


查看完整回答
反对 回复 2022-09-26
?
慕无忌1623718

TA贡献1744条经验 获得超4个赞

Golang 希望程序读取放入频道的消息。

使用者(读取器)需要从通道中抽取(读取)所有消息,无论是使用简单的供读还是供选择。通道发送和接收都阻塞,直到发送方和接收方准备就绪。

  • 案例 1, 案例 2 = 向通道发送一条消息,阻止等待读取器,读取零条消息

  • case4 = 向通道发送一条消息,阻止等待读取器,读取器不消耗(读取)消息

  • case3 = 将一条消息发送到通道,从通道消耗一条消息,发送方阻止等待读取器

  • case5 = 向通道发送五条消息,消耗所有 (五) 条消息,每个发送块直到读取器接收

  // for range over channel

    for msg := range ch {

        // process msg

    }

    

    // for select

    done := false

    for !done {

        select {

            case msg := <-ch: {

                // process msg

            }

            case ch == nil: {

                done = true

            }

        }

    }

    

    // producer should close channel

    close(ch)

注意:

  • 通道可以缓冲,指定通道(队列)大小

  • 通道大小默认值 = 1(无缓冲),通道满时写入器块



查看完整回答
反对 回复 2022-09-26
  • 2 回答
  • 0 关注
  • 72 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信