While your solution might work I'm not happy with it.
First, the fact that you need to change the channel size to make it work indicates that there is a potential problem / bug. Now each time you want to launch another doSomething
you have to remember to change channel's length.
Second, you wait until all the goroutines are finished before reading from the channel. This is kind of "waste" as one of the main points of range loop over an channel is that you don't have to wait until all the items are generated (written into channel), you can start processing the items as soon as some of them are ready.
So I would write your code as something like
func main() {
c := make(chan int)
var wg sync.WaitGroup
wg.Add(3)
go func() {
doSomething(c)
defer wg.Done()
}()
go func() {
doSomething(c)
defer wg.Done()
}()
go func() {
doSomething(c)
defer wg.Done()
}()
go func() {
wg.Wait()
defer close(c)
}()
for v := range c {
fmt.Print(v)
}
}
func doSomething(c chan<- int) {
c <- 1
}
https://play.golang.org/p/T3dfiztKot
Note how the waiting and closing the channel is now in it's own goroutine - this allows to start iterating over the channel (which is now unbuffered!) right away.
I also changed the code so that the WaitGroup
never leaves the scope where it is declared (ie it isn't used as parameter), this is my personal preference. I believe it makes code easier to follow and understand.