Simplest, cleanest and “scalable” way to do it is to use a sync.WaitGroup
:
var wg = &sync.WaitGroup{}
func printElo() {
defer wg.Done()
fmt.Printf("Elo\n")
}
func printHello() {
defer wg.Done()
fmt.Printf("Hello\n")
}
func main() {
fmt.Printf("This will print.")
i := 0
for i < 10 {
wg.Add(1)
go printElo()
wg.Add(1)
go printHello()
i++
}
wg.Wait()
}
Output (try it on the Go Playground):
This will print.Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Simple “rules” to follow when doing it with sync.WaitGroup
:
- call
WaitGroup.Add()
in the “original” goroutine (that starts a new) before thego
statement - recommended to call
WaitGroup.Done()
deferred, so it gets called even if the goroutine panics - if you want to pass
WaitGroup
to other functions (and not use a package level variable), you must pass a pointer to it, else theWaitGroup
(which is a struct) would be copied, and theDone()
method called on the copy wouldn’t be observed on the original