Hello Jon
I think this is working as expected.
The relevant part of the doc is "calls with a positive delta that start when the counter is greater than zero, may happen at any time".
This is what happens in your code (stdout on the left, my comments on the right)
here wg is created, its counter is 0
here after first Add, counter is now 1
waiting
...here the first child goroutine is sleeping for 1s...
adding from top level goroutine
here after second Add, counter is now 2done from top level goroutine
here after Done, counter is now 1done from background goroutine
here after Done, counter is now 0
There are 3 goroutines involved, and while a few different interleaving of messages are possible, what is important here is that
- the first Add happens-before wg.Wait()
- the first Add happens-before the second Add
- the second Add
happens-before the calls to Done, which implies that the second Add start when the counter is greater than zero (it is 1)
The part of the doc that you quote "If a WaitGroup is reused..." warns against a race condition between a "Wait" and an "Add positive number to a zero counter", which is not the case here.
I think it can be rephrased as "make sure all the calls to wg.Wait have properly returned (happen-before) and then you may start reusing the WaitGroup if you wish".
As a side note, you have correctly spotted that it is legal to pass around a pointer to the WaitGroup (as opposed to passing it by value, which would be illegal). But in simple cases like this one, it is even more idiomatic (and legible) to use it directly from the closures scope :
https://play.golang.org/p/nF9Am77e4u-
Hope this helps :)
Don't hesitate to ask for details on this topic
Valentin