Go 的“append”函数出现意外覆盖问题
在 Go 中,append 函数经常用于用附加元素扩展切片。但是,有时,将指针附加到结构时可能会出现意外行为。
考虑以下代码片段:
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) } }
有趣的是,而不是打印 {0} {1} {2} { 3},代码输出 {0} {3} {3} {3}。这种意外的行为源于 Go 行为的一个基本方面:
在 for Range 循环中进行复制
Go 使用 for range 循环迭代切片和数组,这会创建一个副本迭代过程中每个元素的值。在我们的代码中,for range 循环变量 e 表示数组元素 b[i] 的临时副本。不幸的是,我们随后将此临时变量的地址附加到切片 a。
修复
要解决此问题,我们需要附加原始数组元素而不是临时副本。通过修改 for 循环以使用索引 i,我们确保将正确的地址附加到切片:
for i := range b { a = append(a, &b[i]) }
此更改会产生 {0} {1} {2} {3 的预期输出}.
行为的原因
Go 缺乏真正的引用导致了这种情况 行为。在使用引用的 C 或 Java 中,循环变量将直接引用数组元素,从而允许通过循环变量进行更改。然而,在 Go 中,循环变量是一个不同的变量,它保存元素的副本,而不是引用。因此,对循环变量所做的更改不会反映在原始数组元素中。
以上是为什么在 Go 的 `append` 函数中追加指针会导致意外覆盖?的详细内容。更多信息请关注PHP中文网其他相关文章!