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?
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)
}
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With