Strange Golang "append" Behavior: Overwriting Values in Slice
In Golang, when appending to a slice, it's essential to understand the distinction between pointer and non-pointer types.
Consider the example code:
import "fmt" type Foo struct { val int } func main() { var a = make([]*Foo, 1) a[0] = &Foo{0} var b = [3]Foo{Foo{1}, Foo{2}, Foo{3}} for _, e := range b { a = append(a, &e) } for _, e := range a { fmt.Printf("%v ", *e) } }
The expected output is {0} {1} {2} {3}, but instead it prints {0} {3} {3} {3}. This is because the for loop operates on copies of the array elements.
When iterating with for ... range, a temporary, loop variable is created and assigned the value of the array element. In this case, the temporary variable is of type Foo. However, when appending to the slice, the address of the temporary variable is added instead of the address of the actual array element.
This temporary variable is overwritten in each loop iteration with the value of the last element of the array, which is Foo{3}. As a result, the slice contains multiple references to the same pointer, pointing to the last element of the array.
To fix the issue, the address of the array element instead of the loop variable should be appended:
for i := range b { a = append(a, &b[i]) }
With this modification, the output is as expected: {0} {1} {2} {3}.
This behavior highlights the importance of understanding Go's type system and the distinction between pointers and non-pointers when working with slices.
The above is the detailed content of Why Does Appending Pointers to a Slice in Go Result in Unexpected Overwritten Values?. For more information, please follow other related articles on the PHP Chinese website!