The problem isn’t that they might be out-of-order. The problem is expecting that they merely might be out-of-order and actually getting missed and duplicated values due to the timing of shared memory access. This was enough of a problem that they [changed the behavior][1] in Go 1.22.
Yes, that was the crux of my question (and was answered by that link when I checked teivah-given link, which linked https://go.dev/blog/loopvar-preview right there as well). Basically I wondered if the example given was really about:
1) In Go, the 'i' variable in the for loop is the same 'i' for each round of the iteration, meaning closures created inside the loop all refer to that same 'i' variable, instead of getting their own copy of it. Very easy to accidentally think the all closures have their own copy of 'i'. Goroutines are only mentioned because in Golang this mistake tends to come up with Goroutines because of a common code pattern.
OR
2) Goroutines themselves either behave or have some weird lexical scope rules in a way I don't know and it doesn't really have to do with closures but an entirely Golang-foreign-alien concept to me I cannot see, and this is why the book example had Goroutines mentioned with the mistake.
I rarely write Go myself so I was curious :) It looks like it was 1) unless I am bad at reading, and I think the Go 1.22 change is good. I could easily imagine myself and others making that mistake even with the knowledge to be careful around this sort of code (the link shows a more complicated example when scrolling down that IMO is a good motivating example).
It was definitely 1. There were ways to demonstrate the issue without involving goroutines, such as by creating a list of closures in a loop, one at each iteration, and then invoking them synchronously after the loop exits. They would all have the same (in this case, final) value of i.
[1]: https://go.dev/blog/loopvar-preview