Race-free doesn’t mean deterministic
I must add that fixing the data races doesn’t make a program execution trace deterministic. There can still be “races” in the sense of “first goroutine that takes a lock accesses first”, in an order that can’t be predicted.
Consider this program:
$ go run -race not-racy.go
However, 2 goroutines are effectively racing to access the shared variable a. The lock guarantees that one of the accesses will always happen-before the other access. The specific order of the accesses may change the next time the program is executed.
In the two cases, the following unfortunate situation was successfully avoided: