Counter
.Inc
callCounter
we'll write a small assertion function assertCount
so the test reads a bit clearer.wantedCount
and fire a goroutine to call counter.Inc()
.A WaitGroup waits for a collection of goroutines to finish. The main goroutine calls Add to set the number of goroutines to wait for. Then each of the goroutines runs and calls Done when finished. At the same time, Wait can be used to block until all goroutines have finished.
wg.Wait()
to finish before making our assertions we can be sure all of our goroutines have attempted to Inc
the Counter
.A Mutex is a mutual exclusion lock. The zero value for a Mutex is an unlocked mutex.
Inc
will acquire the lock on Counter
if they are first. All the other goroutines will have to wait for it to be Unlock
ed before getting access.sync.Mutex
is embedded into the struct.Lock
and Unlock
is at best confusing but at worst potentially very harmful to your software if callers of your type start calling these methods.go vet
on your code you should get an error like the followingA Mutex must not be copied after first use.
Counter
(by value) to assertCounter
it will try and create a copy of the mutex.Counter
instead, so change the signature of assertCounter
Counter
rather than a *Counter
. To solve this I prefer to create a constructor which shows readers of your API that it would be better to not initialise the type yourself.Counter
.Mutex
allows us to add locks to our dataWaitGroup
is a means of waiting for goroutines to finish jobsA common Go newbie mistake is to over-use channels and goroutines just because it's possible, and/or because it's fun. Don't be afraid to use a sync.Mutex if that fits your problem best. Go is pragmatic in letting you use the tools that solve your problem best and not forcing you into one style of code.