登录
首页 >  Golang >  Go问答

奇怪的golang“追加”行为(覆盖切片中的值)

来源:Golang技术栈

时间:2023-04-28 07:10:00 119浏览 收藏

欢迎各位小伙伴来到golang学习网,相聚于此都是缘哈哈哈!今天我给大家带来《奇怪的golang“追加”行为(覆盖切片中的值)》,这篇文章主要讲到golang等等知识,如果你对Golang相关的知识非常感兴趣或者正在自学,都可以关注我,我会持续更新相关文章!当然,有什么建议也欢迎在评论留言提出!一起学习!

问题内容

我有这个简单的代码:

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循环中您使用的是 副本 而不是切片/数组元素本身。

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

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

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

输出(在Go Playground上试试):

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

查看可能重复的[分配指针字段变为 ](https://stackoverflow.com/questions/34760950/assigned- pointer-field-becomes-nil)。

这种行为的推理

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

摘自此答案

指针是值,就像我们说int数字一样。不同之处在于该值的解释:指针被解释为内存地址,而ints 被解释为整数。

当你想改变类型变量的值时int,你传递一个指向int类型变量的指针*int,然后修改指向的对象:(*i = newvalue分配的值是一个int)。

指针也是如此:当您想更改指针类型变量的值时*int,您将指针传递给该*int类型的变量**int并修改指向的对象:(*i = &newvalue分配的值是 an *int)。

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

今天关于《奇怪的golang“追加”行为(覆盖切片中的值)》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!

声明:本文转载于:Golang技术栈 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>