Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. Go Dictionary
  3. sync.WaitGroup

sync.WaitGroup

sync.WaitGroup is a synchronization primitive used in Go's concurrent programming to wait for goroutines to finish. It uses a counter to block the main flow until all goroutines have completed.

Syntax

import "sync"

var wg sync.WaitGroup

// Increments the counter by N. Call this before launching a goroutine.
wg.Add(N)

// Decrements the counter by 1. The idiomatic way is to call it with defer inside a goroutine.
wg.Done()

// Blocks until the counter reaches 0.
wg.Wait()

// Typical pattern
for i := 0; i < 5; i++ {
    wg.Add(1)
    go func(i int) {
        defer wg.Done() // Guaranteed to be called when the function exits.
        // goroutine work here
    }(i)
}
wg.Wait() // Waits until all goroutines have completed.

Method List

MethodDescription
Add(delta int)Adds delta (positive or negative) to the counter. Call this before launching a goroutine.
Done()Decrements the counter by 1. Equivalent to Add(-1). Call this when a goroutine finishes.
Wait()Blocks the caller until the counter reaches 0.

Sample Code

package main

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

// Processes an item concurrently.
func processItem(id int, wg *sync.WaitGroup) {
    defer wg.Done() // Always calls Done() when the function exits.
    fmt.Printf("Item %d: starting\n", id)
    time.Sleep(time.Duration(id*50) * time.Millisecond) // Simulates processing time.
    fmt.Printf("Item %d: done\n", id)
}

func main() {
    var wg sync.WaitGroup

    // Launch 5 goroutines.
    for i := 1; i <= 5; i++ {
        wg.Add(1) // Increment the counter before launching the goroutine.
        go processItem(i, &wg)
    }

    fmt.Println("Waiting for all goroutines to finish...")
    wg.Wait() // Blocks until every goroutine has called Done().
    fmt.Println("All processing complete!")

    fmt.Println()

    // Pattern for safely collecting results (combined with a mutex).
    var (
        wg2    sync.WaitGroup
        mu     sync.Mutex
        results []int
    )

    for i := 0; i < 5; i++ {
        wg2.Add(1)
        go func(n int) {
            defer wg2.Done()
            result := n * n
            mu.Lock()
            results = append(results, result) // Exclusive access via mutex.
            mu.Unlock()
        }(i)
    }

    wg2.Wait()
    fmt.Println("Squared results (order not guaranteed):", results)
}

Notes

sync.WaitGroup is the most commonly used synchronization primitive for waiting on goroutines. Always pass a WaitGroup by pointer — never by value. Also, Add() must be called before launching a goroutine. Calling Add() inside a goroutine can cause a race condition.

A WaitGroup must be passed as a pointer (*sync.WaitGroup), not as a value. Copying it by value also copies its internal state, which breaks synchronization. Also, calling Done() more times than Add() will make the counter go negative and cause a panic.

For goroutine basics, see goroutine. For exclusive access to shared data, see sync.Mutex / RWMutex.

If you find any errors or copyright issues, please .