doubingguan3425 2016-05-24 07:23
浏览 25
已采纳

Golang:无法在频道上发送

Why is it not sending on the channel and blocking the execution? How can I make this constellation work so that I can send a signal into MoneyDive() and continue execution?

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条回答 默认 最新

  • duanlvji4780 2016-05-24 07:27
    关注

    Because you have an unbuffered channel, and you can only send a value on an unbuffered channel without blocking if there is another goroutine which is ready to receive from it.

    Since you only have 1 goroutine, it gets blocked. Solution is simple: launch your Quack.quack() method in a new goroutine:

    go self.quack(ch)
    

    Then the output (try it on the Go Playground):

    mockQuack start
    mockQuack done
    true
    

    Another option is to not launch a new goroutine but make a buffered channel, so it can hold some values without any receivers ready to receive from it:

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

    This creates a channel which is capable of "storing" one value without any receivers ready to receive it. A second send on the channel would also block, unless the value is received from it first (or a receiver ready to receive a value from it).

    Try this buffered channel version on the Go Playground.

    Relevant section from the spec: 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.

    Notes:

    Based on the received value you print true or false. This can be done with a single line, without the if statement:

    fmt.Println(b)
    

    You can even get rid of the b local variable, and print the received value right away:

    fmt.Println(<-ch)
    

    Also I assume you used channels because you wanted to play with them, but in your case mockQuack() could simply return the bool value, without the use of channels.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 HFSS 中的 H 场图与 MATLAB 中绘制的 B1 场 部分对应不上
  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?