英文:
Concurrent send/receive go channel
问题
我有一个叫做queue
的go通道,假设缓冲区大小为100。许多go协程可以向该通道发送数据,而另一个go协程则负责从该通道接收数据。这是一个持久的过程,意味着该通道就像一个管道,从多个端口吸收数据并将数据传输到一个端口。在接收的go协程中,我做了以下操作:
for {
for data := range queue {
sink(data)
}
}
现在我的问题是:如果在range循环结束之前,有一些新数据被发送到通道缓冲区,那么这些新数据是否会在下一个range循环中可用?如果在这种情况下没有考虑并发,它们会被忽略吗?
英文:
I have a go channel called queue
with let's say 100 as the buffer size. Many go routines can send data to this channel, and another go routine is sitting there to receive data from this channel. This is a long lasting process, meaning the channel is acting like a pipeline absorbing data from many ends and sinking data to one end. I do something like this in the receiving go routine:
for {
for data := range queue {
sink(data)
}
}
Now my question is: what if some new data were sent to the channel buffer before the range loop is finished. Will the new data be available for the next range loop? Or they will be missed if concurrency is not taken into consideration in this case?
答案1
得分: 5
你只需要一个for
循环。根据range表达式的规范:
> 对于通道,产生的迭代值是连续发送到通道上的值,直到通道关闭。如果通道为nil
,则range表达式将永远阻塞。
在这种情况下,range循环不像普通的范围循环那样,例如对切片进行迭代。相反,当可以从通道中读取项目时,循环体对其进行处理。因此,你的嵌套循环应该被以下代码所替代:
for data := range queue {
sink(data)
}
英文:
You only need one for
loop. From the spec on range expressions:
> For channels, the iteration values produced are the successive values sent on the channel until the channel is closed. If the channel is nil
, the range expression blocks forever.
In this case, the range loop is not acting like a regular range over, for example, a slice. Instead, when an item can be read from the channel, the loop body processes it. Therefore, your nested loops should be replaced with the following:
for data := range queue {
sink(data)
}
答案2
得分: 4
根据@Tim的说法,你只需要一个单独的for
循环,因为range
会从通道中发出值,直到通道关闭。
总的来说,你描述的模式被称为扇入。一个基本的生产者/消费者设置示例可以在这里找到:http://play.golang.org/p/AhQ012Qpwj。range
循环在消费者中运行:
// 消费者充当扇入,当完成时发出信号。
func consumer(out chan string, done chan bool) {
for value := range out {
fmt.Println(value)
}
done <- true
}
英文:
As @Tim said, you only need a single for
, since range
will emit values from the channel, until it is closed.
Overall, the pattern you describe is called fan-in. A example for a basic producer/consumer setup can be found here: http://play.golang.org/p/AhQ012Qpwj. The range loop runs in the consumer:
// consumer acts as fan in, signals when it is done.
func consumer(out chan string, done chan bool) {
for value := range out {
fmt.Println(value)
}
done <- true
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论