【问题标题】:More idiomatic way of adding channel result to queue on completion在完成时将通道结果添加到队列的更惯用方式
【发布时间】:2011-03-08 23:31:42
【问题描述】:

所以,现在,我只需传递一个指向 Queue 对象的指针(实现并不重要)并在应该向队列中添加内容的 goroutine 的末尾调用 queue.add(result)

我需要同样的功能——当然,与简单的队列添加函数调用相比,使用逗号 ok 语法进行循环检查完成在性能方面是不可接受的。

有没有更好的方法?

【问题讨论】:

  • 您到底想完成什么?据我所知,您不需要队列对象,只需要一个通道。然后在每个 goroutine 结束时执行 channel
  • 好吧,我有频道生成一个需要一些时间来创建的对象;一直在生成其中的几个对象(通过循环)。创建对象后,我需要将其放入队列中,以便程序的另一部分可以在单独的 goroutine 中不断地处理这些已完成的 goroutine。我知道channel <- result 正在阻塞——这不是我真正想要的。
  • 通道可以被缓冲,make(chan rtype, BUFFER_SIZE),在这种情况下发送不会阻塞,除非缓冲区已满。如果你真的需要一个无限缓冲的队列,有一个带有小缓冲区的结果通道和另一个从通道读取并将结果存储在容器/向量中的 goroutine。Vector

标签: go channel goroutine


【解决方案1】:

你的问题实际上有两个部分:一个是如何在 Go 中排队数据,一个是如何在不阻塞的情况下使用通道。

对于第一部分,听起来您需要做的不是使用通道将内容添加到队列中,而是将通道用作队列。例如:

var (
    ch = make(chan int) // You can add an int parameter to this make call to create a buffered channel

    // Do not buffer these channels!
    gFinished = make(chan bool)
    processFinished = make(chan bool)
)
func f() {
    go g()
    for {
        // send values over ch here...
    }
    <-gFinished
    close(ch)
}
func g() {
    // create more expensive objects...
    gFinished <- true
}
func processObjects() {
    for val := range ch {
        // Process each val here
    }
    processFinished <- true
}
func main() {
    go processObjects()
    f()
    <-processFinished
}

至于如何使这更加异步,您可以(正如 cthom06 指出的那样)将第二个整数传递给第二行中的 make 调用,这将使发送操作异步,直到通道的缓冲区已满。

编辑: 但是(正如 cthom06 也指出的那样),因为您有两个 goroutine 写入通道,其中一个必须负责关闭通道。此外,我之前的修订版将在 processObjects 完成之前退出。我选择同步 goroutine 的方式是创建更多通道来传递虚拟值,以确保清理正确完成。这些通道是专门无缓冲的,因此发送会同步进行。

【讨论】:

    猜你喜欢
    • 2021-09-05
    • 1970-01-01
    • 1970-01-01
    • 2010-10-21
    • 2017-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多