In Golang, you can use WaitGroup to await a collection of goroutines to finish. Let's take a look at the below example

package main

import (  
    "fmt"
    //"time"
)

func f(s string) {  
    fmt.Println(s)
}

func main() {  
    go f("i'm async!")

    go func(s string) {
        fmt.Println(s)
    }("i'm async too!")

    //time.Sleep(time.Second)
    fmt.Println("done!")
}

The number of output strings will vary as the program may have exited before all goroutines completion.

You can use time.Sleep by assuming a duration, however sync.WaitGroup is a better way in practice to handle the case. The following gives you an implementation example with WaitGroup


WaitGroup is a struct defined in the sync package. It maintains a counter to wait for a collection of goroutines to finish. In the above program

  • waitGroup.Add(1) adds a delta to the WaitGroup counter

  • waitGroup.Done() decreases the WaitGroup counter by one

  • waitGroup.Wait() blocks until the WaitGroup counter is zero

Now, the quantity of output strings is always consistent (the ordering may be different for each invocation)

i'm async too!  
i'm async!  
done!  

WaitGroup.Wait() timeout

WaitGroup.Wait() doesn't have a timeout option. The following example gives you an implementation example by using channel and select


Output

i'm async!  
Wait timeout!  

A select blocks until one of its cases is ready to run

In the above waitTimeout method definition, the second select case is ready before the first case as the second goroutine execution time (time.Sleep(2*time.Second)) is greater than the wait timeout parameter (waitGroup.waitTimeout(time.Second)). You can try to comment out the line time.Sleep(2*time.Second) to see the different outputs