我在我的函数中接受done
频道,这对于在某些异步过程完成时通知调用者很有用,如果他们在意的话。例如,这对于编写单元测试非常有用。
如果我的呼叫者不需要此功能,是否有一种惯用的方法来传递垃圾信道,其中发送给它的所有值都会立即被丢弃?我最初感到惊讶的是发送nil
没有工作(发送给nil阻止发件人)。我可以想到一个粗略的实现(就像goroutine总是在这个频道上消耗的那样),但是我想写下这样的东西:
func myFunc(foo int, done chan bool) {
....
}
func main() {
myfunc(4, _)
}
有一种简单的方法可以实现这一目标吗?
答案 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)
}