Yes. Per rsc (https://research.swtch.com/gorace)
> In the current Go implementations, though, there are two ways to break through these safety mechanisms. The first and more direct way is to use package unsafe, specifically unsafe.Pointer. The second, less direct way is to use a data race in a multithreaded program.
That races undermine memory safety in go has been used in CTFs: https://github.com/netanel01/ctf-writeups/blob/master/google...
These are not idle fancies, there are lots of ways to unwittingly get data races in go: https://www.uber.com/blog/data-race-patterns-in-go.
In C and C++ SC/DRF (Sequentially Consistent if Data Race Free) turns into "All data races are Undefined Behaviour, game over, you lose". In Go SC/DRF turns into "All data races on complex types are Undefined Behaviour, game over, you lose". If you race e.g. a simple integer counter, it's damaged and you ought not to use it because it might be anything now, but Go isn't reduced to Undefined Behaviour immediately for this seemingly trivial mishap (whereas C and C++ are)
The reasons C compilers “tend to go out of their way to make weird things happen” is they optimise extremely aggressively, and optimisations are predicated upon the code being valid (not having UBs).
Go barely optimises at all, and does not have that many UBs which could send the optimiser in a frenzy.
Implicitly shared memory is literally the default behaviour of the langage, and you have to be careful to keep that controlled or contained.
Pretty much as in every other shared memory concurrency langage.
The quip about sharing memory by communicating is cute but it’s just that, the langage does not encourage let alone enforce it.
In fact it went out of its way to remove some opportunities e.g. because `go` is a statement there is no handle which could communicate the termination and result of routines.