On Tue, Dec 18, 2018 at 5:35 AM Chris Burkert <burkert.ch...@gmail.com> wrote: > > I have a couple of goroutines sending multiple results over a channel - a > simple fan-in. They signal the completion on a done channel. Main selects on > the results and done channel in parallel. As the select is random main > sometimes misses to select the last result. What would be the idiomatic way > to prevent this and completely drain the result channel? > > Here is a minmal example which sometimes prints one 0 but should always print > two of them: > > package main > > import ( > "fmt" > ) > > func do(rc chan<- int, dc chan<- bool) { > rc <- 0 > dc <- true > } > > func main() { > worker := 2 > rc := make(chan int, worker) > done := 0 > dc := make(chan bool, worker) > for i := 0; i < worker; i++ { > go do(rc, dc) > } > for done < worker { > select { > case <-dc: > done++ > case r := <-rc: > fmt.Println(r) > } > } > }
I assume the workers can generate multiple results, as otherwise the done marker seems pointless. In general the simplest way to signal completion on a channel is to call close. The simplest way to call close on a fan-in is to have another goroutine that waits for the other goroutines and closes the channel. That might look like package main import ( "fmt" "sync" ) func do(rc chan<- int) { rc <- 0 } func main() { worker := 2 rc := make(chan int, worker) var wg sync.WaitGroup wg.Add(worker) for i := 0; i < worker; i++ { go func() { defer wg.Done() do(rc) }() } go func() { wg.Wait() close(rc) }() for r := range rc { fmt.Println(r) } } Ian -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.