Iterating Over Values
Developers might be shocked by the results of this code:
package main
import (
"fmt"
)
func main() {
x := []int{3, 9, 2, 6, 4}
y := make([]*int, 5)
for i, v := range x {
y[i] = &v
}
for _, v := range y {
fmt.Printf("%d, ", *v)
}
}
import (
"fmt"
)
func main() {
x := []int{3, 9, 2, 6, 4}
y := make([]*int, 5)
for i, v := range x {
y[i] = &v
}
for _, v := range y {
fmt.Printf("%d, ", *v)
}
}
When run, it prints the following:
4, 4, 4, 4, 4,
Why is that? It seems like it just used the last value in x for everything? This happens because in the for loop, the variable “v” is updated in its place. The “y[i]” is pointing to “v”, but its value keeps getting overwritten.
There is a workaround for this situation, the value can be copied to a new local variable within the loop.
package main
import (
"fmt"
)
func main() {
x := []int{3, 9, 2, 6, 4}
y := make([]*int, 5)
for i, v := range x {
v2 := v
y[i] = &v2
}
for _, v := range y {
fmt.Printf("%d, ", *v)
}
}
import (
"fmt"
)
func main() {
x := []int{3, 9, 2, 6, 4}
y := make([]*int, 5)
for i, v := range x {
v2 := v
y[i] = &v2
}
for _, v := range y {
fmt.Printf("%d, ", *v)
}
}
Now when this runs, it prints what we expected:
3, 9, 2, 6, 4,
This problem occurs whenever we have a for loop that iterates over values, not pointers, and within the loop we capture a pointer to that value.