【问题标题】:Garbage channel in Golang?Golang 中的垃圾通道?
【发布时间】:2017-04-29 02:31:34
【问题描述】:

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

如果我的调用者不需要此功能,是否有一种惯用的方式来传递垃圾通道,发送给它的所有值都会立即被丢弃?我最初很惊讶发送nil 不起作用(发送到 nil 会阻止发件人)。我可以想到一个粗略的实现(比如一个始终运行的 goroutine,它从这个频道消费),但我很想写这样的东西:

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

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

有没有一种简单的方法可以做到这一点?

【问题讨论】:

  • 为什么不检查 nil 并将其替换为虚拟值?
  • @JimB 你的虚拟值是make (chan bool, x),x 是我要写的次数吗?我可以避免分配内存/GC-ing 我以后写在那里的东西吗?
  • 用于信号的通道通常只关闭一次。如果这些值真的有用,那么是的,您要么需要使用它们,要么需要缓冲它们。如果这些值只是哨兵,您应该使用sync.WaitGroup
  • 可能值得注意的是,提供一个名为“done”的通道也很常见,该通道仅对信号完成关闭。大多数 Go 程序员都不会使用“完成”通道返回值。

标签: go channel


【解决方案1】:

这个怎么样:

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

【讨论】:

    【解决方案2】:

    您可以在发送时使用 select 来避免阻塞:

    select {
    case done <- true:
    default:
    }
    

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

    不过,值得注意的是关闭 nil 通道,而不是阻塞,恐慌,所以你仍然需要对其进行 nil 检查。

    编辑:我喜欢的风格:

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

    编辑 2:您甚至可以将其设为可变参数,允许省略 done 通道,提供多个通道。

    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)
    

    【讨论】:

      猜你喜欢
      • 2022-01-08
      • 1970-01-01
      • 2011-12-22
      • 2011-01-04
      • 1970-01-01
      • 1970-01-01
      • 2017-05-07
      • 1970-01-01
      • 2016-10-31
      相关资源
      最近更新 更多