Waitgroup Add In Goroutine

ID

go.waitgroup_add_in_goroutine

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

Go

Tags

concurrency, reliability

Description

Reports a wg.Add(…​) call placed inside the body of a goroutine started with go func() { …​ }(). A sync.WaitGroup must be told about a goroutine before that goroutine is launched.

Rationale

When Add runs inside the goroutine, the launching side may reach wg.Wait() before the goroutine has had a chance to run Add. Wait then sees a counter of zero, returns immediately, and the program proceeds as if the work were finished — a data race that fails intermittently and is hard to reproduce. Calling Add before the go statement guarantees the counter is non-zero by the time Wait is reached.

go func() {
    wg.Add(1)      // FLAW — Add runs inside the goroutine
    defer wg.Done()
}()

wg.Add(1)          // OK — Add before launching the goroutine
go func() {
    defer wg.Done()
}()

Remediation

Move the wg.Add(…​) call out of the goroutine body so it executes before the go statement that launches the goroutine.