Golang:无法发送频道

时间:2016-05-24 07:23:18

标签: go concurrency channel

为什么不在频道上发送并阻止执行?如何使这个星座工作,以便我可以向MoneyDive()发送信号并继续执行?

package main

import (
    "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 个答案:

答案 0 :(得分:3)

因为你有一个无缓冲的频道,你只能在没有阻止的情况下在无缓冲的频道上发送一个值,如果有另一个goroutine已准备好接收它。

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

go self.quack(ch)

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

mockQuack start
mockQuack done
true

另一个选择是不启动新的goroutine但是创建一个缓冲的通道,因此它可以保存一些值,而没有任何接收器可以从它接收:

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

这创建了一个能够&#34;存储&#34;没有任何接收器准备接收它的一个值。除非首先从它接收到值(或接收器准备从其接收值),否则通道上的第二次发送也将阻塞。

Go Playground上尝试此缓冲频道版本。

规范中的相关部分:Send statements:

  

在通信开始之前评估通道和值表达式。 通信阻止,直到发送可以继续。如果接收器准备就绪,则可以继续在无缓冲信道上发送。如果缓冲区中有空间,则缓冲信道上的发送可以继续。通过导致run-time panic继续在封闭频道上发送。 nil 频道上的发送会永久阻止。

备注:

根据收到的值,您可以打印truefalse。这可以使用一行完成,不需要if语句:

fmt.Println(b)

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

fmt.Println(<-ch)

此外,我假设您使用了频道,因为您想要使用这些频道,但在您的情况下,mockQuack()只需返回bool值,而无需使用频道。