If I have 2 5 goroutine for read, and 1 goroutine for write, is there a way to make sure that every goroutine gets the entire write data?
For example.
In the following code whenever I write to main thread, one and only one goroutine gets the value.
package main
import (
"fmt"
"sync"
"time"
)
func main() {
c := make(chan int)
var w sync.WaitGroup
w.Add(5)
for i := 1; i <= 5; i++ {
go func(i int, ci <-chan int) {
j := 1
for v := range ci {
time.Sleep(time.Millisecond)
fmt.Printf("%d.%d got %d\n", i, j, v)
j += 1
}
w.Done()
}(i, c)
}
for i := 1; i <= 25; i++ {
c <- i
}
close(c)
w.Wait()
}
I want to make sure all goroutine gets the entire value 1-25
in a non blocking manner. For example one goroutine can read the entire 1-25 and finish processing, while others can still be reading all the data.
If I want to do this, do I have to create 25 channels? Or is there more subtle way of maintaining the desired behavior.
评论:
gdey:
icholy:Yes, you would need to create 5 channels, make it buffered so it does not block, one for each goroutine, and send the values to each channel.
In the play version I increased the sleep based on the i of the goroutine, to show that go routines complete and don't wait.
Here is go playground
package main import ( "fmt" "sync" "time" ) func main() { var chans [5]chan int for i := range chans { chans[i] = make(chan int, 25) } var w sync.WaitGroup w.Add(5) for i := 0; i < 5; i++ { go func(i int, ci <-chan int) { j := 1 for v := range ci { time.Sleep(time.Millisecond) fmt.Printf("%d.%d got %d\n", i, j, v) j += 1 } w.Done() }(i+1, chans[i]) } for i := 1; i <= 25; i++ { for _, c := range chans { c <- i } } for _, c := range chans { close(c) } w.Wait() }
When there are many consumers the delivery semantics are basically round robin (kinda), if you want to do a fan-out pattern you have to do it yourself.
