gpt4 book ai didi

arrays - 奇怪的 golang "append"行为(覆盖 slice 中的值)

转载 作者:IT王子 更新时间:2023-10-29 01:07:56 27 4
gpt4 key购买 nike

我有这个简单的代码:

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}。这里发生了什么?

最佳答案

这是因为在 for 循环中,您操作的是一个副本,而不是 slice/数组元素本身。

for ... range 复制它循环的元素,然后 append 这个临时循环变量的地址——它在所有迭代中都是相同的。所以你添加了同一个指针 3 次。并且这个临时变量将在最后一次迭代(数组的最后一个元素)中设置为 Foo{3},所以这就是为什么您看到打印了 3 次。

修复:不添加循环变量的地址,而是添加数组元素的地址:

for i := range b {
a = append(a, &b[i])
}

输出(在 Go Playground 上尝试):

{0} {1} {2} {3} 

查看可能重复的 Assigned pointer field becomes <nil> .

此行为的原因

Go 中有指针 类型和非指针 类型,但没有"references" (在 C++ 和 Java 中使用它的意思)。鉴于 Go 中没有“引用”类型这一事实,这并不是意外行为。循环变量只是一个“普通”的局部变量,它只能保存一个值(可以是指针或非指针),不能保存引用。

摘自 this answer :

Pointers are values just like let's say int numbers. The difference is the interpretation of that value: pointers are interpreted as memory addresses, and ints are interpreted as integer numbers.

When you want to change the value of a variable of type int, you pass a pointer to that int which is of type *int, and you modify the pointed object: *i = newvalue (the value assigned is an int).

Same goes with pointers: when you want to change the value of a variable of pointer type *int, you pass a pointer to that *int which is of type **int and you modify the pointed object: *i = &newvalue (the value assigned is an *int).

总而言之,循环变量只是一个普通变量,具有您要循环的数组/slice 的元素类型,并且要使其具有实际迭代的值,必须为其分配值复制值。它在下一次迭代中被覆盖。

关于arrays - 奇怪的 golang "append"行为(覆盖 slice 中的值),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38692998/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com