Every language has an arsenal of footguns. Go is no different. I would say that overall it is not too bad, comparatively. From all the listed cases, only the first one is easy to get caught by, even as an experienced developer. There, the IDE and syntax highlighting is of tremendous help and for general prevention. The rest is just understanding the language and having some practice.
I'm still relatively new to Go, but I've never seen closures used that often thus far in production code. Is it really a common practice?
As to whether it's a common pattern, I see closures on WaitGroups or ErrGroups quite often:
workerCount := 5
var wg sync.WaitGroup
wg.Add(workerCount)
for range workerCount {
go func() {
// Do work
wg.Done()
}()
}
wg.Wait()
You can avoid the closure by making the worker func take a *sync.WaitGroup and passing in &wg, but it doesn't really have any benefit over just using the closure for convenience.