The loop semantics do not have anything to do with arrays. The point of confusion is whether a new slot for data is being created before each iteration, or whether the same slot is being used for each iteration. It turns out that the same slot is being used. The Go code itself is clear `for i := 0; i < 10; i++`. `i := 0` is where you declare i. Nothing else would imply that space is being allocated for each iteration; the first clause of the (;;) statement is only run before the loop. So you're using the same i for every iteration. This is surprising despite how explicit it is; programmers expect that a new slot is being allocated to store each value of i, so they take the address to it, and are surprised when it's at the same address every iteration. (Sugar like `for i, x := range xs` is even more confusing. The := strongly implies creating a new i and x, but it's not doing that!)
Basically, here are two pseudocode implementations. This is what currently happens:
i = malloc(sizeof(int))
*i = 0
loop:
<code>
*i = *i + 1
goto loop if *i < 10
You can see that they are not crazy for picking the first implementation; it's less instructions and less code, AND the for loop is pretty much exactly implementing what you're typing in. It's just so easy to forget what you're actually saying that most languages are choosing to do something like the second example (though no doubt, not allocating 8 bytes of memory for each iteration).
Remember, simple cases work:
for i := 0; i < 10; i++ {
fmt.Println(i) // 0 1 2 3 4 ...
}
It's the tricky cases that are tricky:
var is []*int
for i := 0; i < 10; i++ {
is = append(is, &i)
}
for _, i := range is {
fmt.Println(*i) // 9 9 9 9 9 ...
}
If you really think about it, the second example is exactly what you're asking for. You declared i into existence once. Of course its address isn't going to change every iteration.
Basically, here are two pseudocode implementations. This is what currently happens:
This is what people expect: You can see that they are not crazy for picking the first implementation; it's less instructions and less code, AND the for loop is pretty much exactly implementing what you're typing in. It's just so easy to forget what you're actually saying that most languages are choosing to do something like the second example (though no doubt, not allocating 8 bytes of memory for each iteration).Remember, simple cases work:
It's the tricky cases that are tricky: If you really think about it, the second example is exactly what you're asking for. You declared i into existence once. Of course its address isn't going to change every iteration.