| It all depends on what you're trying to do. These cases work flawlessly in Go, in my experience: * Batch 10 tasks and run them concurrently (using WaitGroups). * Locking resources while reading and writing with a mutex like sync.RWMutex, using .Lock() and .Unlock(), often together with defer. * Locking resources while only reading with a sync.RWMutex, using .RLock() and .RUnlock(), often together with defer. * Running code "in the background" with goroutines, ie. go func() { <code goes here> }(). * Detecting race conditions by building with go build -race and then running the program. However, when using channels, select, closing channels, waiting on channels in a for loop etc, things can easily become more subtle. On a general basis, I disagree that concurrency bugs are easy to introduce and hard to find in Go. However, pure functional programming languages like Haskell, with little state, will always have the upper hand when it comes to concurrency. See also: https://gobyexample.com/waitgroups https://gobyexample.com/mutexes https://gobyexample.com/defer https://gobyexample.com/goroutines https://gobyexample.com/non-blocking-channel-operations |