Golang:无法在频道上发送

Golang: cannot send on 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

因为你有一个 unbuffered 通道,如果有另一个 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

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

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

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

Both the channel and the value expression are evaluated before communication begins. Communication blocks until the send can proceed. A send on an unbuffered channel can proceed if a receiver is ready. A send on a buffered channel can proceed if there is room in the buffer. A send on a closed channel proceeds by causing a run-time panic. A send on a nil channel blocks forever.

备注:

根据接收到的值打印 truefalse。这可以用一行完成,没有 if 语句:

fmt.Println(b)

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

fmt.Println(<-ch)

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