This is by no mean the definitive guide. I’m just going to highlight some tools and patterns in concurrency programming that I have seen.
Mutex
Extremely useful when guarding a variable unsafe read and writes.
- RWMutex
- Mutex
var mu sync.Mutex
struct not pointer
func (s *myStruct) GetItem() *Item {
s.mu.RLock()
defer s.mu.RUnlock()
return s.item
}
Waitgroup for synchronization/orchestration
var wg &sync.Waitgroup
wg.Add(num)
for i := 0; i < num; i ++ {
// start consumer
go func() {
setUpCode()
wg.Done()
}()
}
// Wait for everything to be ready
wg.Wait()
Channels for two way sync
commC := make(chan struct{})
go func() {
// blocks until setup 1 is done
commC<-struct{}{}
// set up 2
close(commC)
doMoreStuffTogether()
}()
// setup 1
<-commC
<-commC
doStuffTogether()
Singleflight
g := &singleflight.Group{}
// this will ensure multiple concurrent calls to this won't do the connection stuff multiple times.
x, y := g.Do(func() (int, int){
// do some connection stuff
return 1, 2
})
Atomic int and bool
- Add, subtract, compare and swap
- Use 1 and 0 for bool
func f() {
var x int
atomic.StoreInt(&x, 1)
}