sync.WaitGroup provides a goroutine synchronization mechanism in Golang, and is used for waiting for a collection of goroutines to finish.

The sync.WaitGroup structure is like this:

type WaitGroup struct {
    m       Mutex
    counter int32
    waiters int32
    sema    *uint32
}

There is a counter member which indicates how many goroutines need to be waited are living now.

sync.WaitGroup also provides 3 methods: Add, Done and Wait. Add method is used to identify how many goroutines need to be waited. When a goroutine exits, it must call Done. The main goroutine blocks on Wait, Once the counter becomes 0, the Wait will return, and main goroutine can continue to run.

Let’s see an example:

package main

import (
    "sync"
    "time"
    "fmt"
)

func sleepFun(sec time.Duration, wg *sync.WaitGroup) {
    defer wg.Done()
    time.Sleep(sec * time.Second)
    fmt.Println("goroutine exit")
}

func main() {
    var wg sync.WaitGroup

    wg.Add(2)
    go sleepFun(1, &wg)
    go sleepFun(3, &wg)
    wg.Wait()
    fmt.Println("Main goroutine exit")

}

Because the main goroutine need to wait 2 goroutines, so the argument for wg.Add is 2. The execution result is like this:

goroutine exit
goroutine exit
Main goroutine exit

Please notice, the Add must go ahead of Done. For detailed inforamtion, you can refer this link: Example for sync.WaitGroup correct?.