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

Golang:无法在频道上发送

Golang:无法在频道上发送

Go
回首忆惘然 2022-01-10 19:10:56
为什么它不在通道上发送并阻止执行?我怎样才能使这个星座工作,以便我可以发送信号MoneyDive()并继续执行?package mainimport (    "fmt")type Quack func(ch chan bool)type DagobertDuck struct {    quack Quack}func (self *DagobertDuck) MoneyDive() {    ch := make(chan bool)    self.quack(ch)    b := <-ch    if b {        fmt.Println("true")    } else {        fmt.Println("false")    }}func mockQuack(ch chan bool) {    fmt.Println("mockQuack start")    ch <- true    fmt.Println("mockQuack done")}func main() {    dd := DagobertDuck{quack: mockQuack}    dd.MoneyDive()}https://play.golang.org/p/1omlb7u6-A
查看完整描述

1 回答

?
慕田峪4524236

TA贡献1875条经验 获得超5个赞

因为你有一个无缓冲的通道,如果有另一个 goroutine 准备好从它接收,你只能在无缓冲的通道上发送一个值而不会阻塞。


由于你只有 1 个 goroutine,它会被阻塞。解决方案很简单:Quack.quack()在一个新的 goroutine 中启动你的方法:


go self.quack(ch)

然后是输出(在Go Playground上试试):


mockQuack start

mockQuack done

true

另一种选择是不启动新的 goroutine 而是创建一个缓冲通道,这样它就可以保存一些值,而无需任何接收器准备好接收它:


ch := make(chan bool, 1) // buffered channel, buffer for 1 value

这将创建一个通道,该通道能够“存储”一个值,而无需任何接收器准备接收它。通道上的第二次发送也会阻塞,除非首先从它接收到值(或者接收器准备好从它接收值)。


在Go Playground上试试这个缓冲通道版本。


规范中的相关部分:发送声明:


通道和值表达式都在通信开始之前进行评估。通信阻塞,直到发送可以继续。如果接收器准备好,则可以在无缓冲通道上进行发送。如果缓冲区中有空间,则可以继续缓冲通道上的发送。关闭通道上的发送会导致运行时恐慌。在nil通道上发送永远阻塞。


笔记:


根据您打印的接收值true或false. 这可以用一行来完成,而不需要以下if语句:


fmt.Println(b)

您甚至可以摆脱b局部变量,并立即打印接收到的值:


fmt.Println(<-ch)

另外我假设您使用通道是因为您想使用它们,但在您的情况下mockQuack()可以简单地返回bool值,而不使用通道。


查看完整回答
反对 回复 2022-01-10
  • 1 回答
  • 0 关注
  • 182 浏览
慕课专栏
更多

添加回答

举报

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