Golang的垃圾通道?

时间:2016-12-13 21:47:43

标签: go channel

我在我的函数中接受done频道,这对于在某些异步过程完成时通知调用者很有用,如果他们在意的话。例如,这对于编写单元测试非常有用。

如果我的呼叫者不需要此功能,是否有一种惯用的方法来传递垃圾信道,其中发送给它的所有值都会立即被丢弃?我最初感到惊讶的是发送nil没有工作(发送给nil阻止发件人)。我可以想到一个粗略的实现(就像goroutine总是在这个频道上消耗的那样),但是我想写下这样的东西:

func myFunc(foo int, done chan bool) {
    ....
}

func main() {
    myfunc(4, _)
}

有一种简单的方法可以实现这一目标吗?

2 个答案:

答案 0 :(得分:4)

您可以在发送时使用选择以避免阻止:

select {
case done <- true:
default:
}

另一种选择,也是我首选的选择,是不通过完成频道发送内容。相反,关闭频道。这导致所有被阻止的接收操作立即同时返回(而不是必须向每个发送一个值),阻止在发送退出信号的函数中阻塞(如果没有正在侦听)。这也允许您用chan struct{}替换频道,这很好,因为struct{}的大小为0。

值得注意的是,关闭一个零通道,而不是阻止,恐慌,所以你仍然必须对它进行零检查。

编辑:我的首选风格:

func myFunc(foo int, done chan<- struct{}) {
    if done != nil {
        defer close(done)
    }
    ....
}

编辑2:您甚至可以使其成为可变参数,这样可以省略完成的通道,可以提供多个。

func myFunc(foo int, done ...chan<- struct{}) {
    for _, d := range done {
        if d != nil {
            defer close(d)
        }
    }
    ....
}
----
myFunc(1)
myFunc(2, ch1)
myFunc(3, ch2, ch3, ch4)

答案 1 :(得分:0)

这个怎么样:

func DoAllTheThings(done ...chan<- bool) {

    // do the things

    // all done!
    if len(done) >= 1 {
        done[0] <- true
    }
    return
}

如果参数中没有给出通道,则不发送任何内容。显然,由呼叫者为频道设置监听器。然后你可以把它称为:

func main() {
    DoAllTheThings()
}

func main() {
    ch := make(chan bool)
    go func() {
        done := <- ch
        if done {
            fmt.Println("Yay!")
        }
    }()
    DoAllTheThings(ch)
}

https://play.golang.org/p/Ktc977gYpA