英文:
More idiomatic way of adding channel result to queue on completion
问题
所以,现在,我只是传递一个指向队列对象的指针(实现并不重要),并在应该向队列中添加东西的goroutine的末尾调用queue.add(result)
。
我需要相同类型的功能,当然,使用逗号ok语法进行循环检查完成是不可接受的,因为性能不如简单的队列添加函数调用。
有没有更好的方法来做到这一点,或者没有?
英文:
So, right now, I just pass a pointer to a Queue object (implementation doesn't really matter) and call queue.add(result)
at the end of goroutines that should add things to the queue.
I need that same sort of functionality—and of course doing a loop checking completion with the comma ok syntax is unacceptable in terms of performance versus the simple queue add function call.
Is there a way to do this better, or not?
答案1
得分: 1
实际上,你的问题有两个部分:如何在Go中排队数据,以及如何在不阻塞的情况下使用通道。
对于第一部分,听起来你需要做的是,不要使用通道将事物添加到队列中,而是将通道作为队列使用。例如:
var (
ch = make(chan int) // 你可以在这个make调用中添加一个int参数来创建一个带缓冲的通道
// 不要给这些通道添加缓冲!
gFinished = make(chan bool)
processFinished = make(chan bool)
)
func f() {
go g()
for {
// 在这里发送值到ch...
}
<-gFinished
close(ch)
}
func g() {
// 创建更昂贵的对象...
gFinished <- true
}
func processObjects() {
for val := range ch {
// 在这里处理每个val
}
processFinished <- true
}
func main() {
go processObjects()
f()
<-processFinished
}
至于如何使这个更加异步,你可以(正如cthomo06指出的)在第二行的make
调用中传递第二个整数,这将使发送操作在通道的缓冲区满之前是异步的。
**编辑:**然而(正如cthomo06也指出的),因为你有两个goroutine写入通道,其中一个必须负责关闭通道。此外,我之前的修订版本会在processObjects完成之前退出。我选择同步goroutine的方式是创建一些额外的通道,传递虚拟值以确保清理工作完成。这些通道特别是无缓冲的,以便发送操作按步骤进行。
英文:
There are actually two parts to your question: how does one queue data in Go, and how does one use a channel without blocking.
For the first part, it sounds like what you need to do is instead of using the channel to add things to the queue, use the channel as a queue. For example:
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
}
As for how you can make this more asynchronous, you can (as cthom06 pointed out) pass a second integer to the make
call in the second line which will make send operations asynchronous until the channel's buffer is full.
EDIT: However (as cthom06 also pointed out), because you have two goroutines writing to the channel, one of them has to be responsible for closing the channel. Also, my previous revision would exit before processObjects could complete. The way I chose to synchronize the goroutines is by creating a couple more channels that pass around dummy values to ensure that the cleanup gets finished properly. Those channels are specifically unbuffered so that the sends happen in lock-step.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论