『Go 基础知识』正在自学golang,在指针这一个知识点遇到了点问题,求解惑。

package main

import “fmt”

type strudent struct {
name string
age int
}

func main() {

m := make(map[string]*strudent, 10)

stus := []strudent{
    {name: "peter", age: 18},
    {name: "lily", age: 25},
    {name: "lucy", age: 20},
}
for _, stu := range stus {
    fmt.Printf("%p\n", &stu)
    m[stu.name] = &stu
}

for k, v := range m {
    fmt.Println(k, "=>", v.name)
}

}
//: <> (对待提问越认真,就越容易得到答复。)
//: <> (对待提问越认真,就越容易得到答复。)
//: <> (对待提问越认真,就越容易得到答复。)
//: <> (重要的事情说三遍!)

1. 运行环境

//: cscci03049> go version
//: go version go1.13.8 linux/amd64

2. 问题描述?

搞不懂为什么在循环遍历的时候,访问到的是同一块内存地址
cscci03049> go run main.go
0xc00000c060
0xc00000c060
0xc00000c060
peter => lucy
lily => lucy
lucy => lucy

3. 您期望得到的结果?

4. 您实际得到的结果?

最佳答案

那不然呢,每次循环分配一次内存??forr 每次循环会重新赋值给 stu ,所以 stu的地址不会变,但这个地址存的数据会变。

1年前 评论
Alone88 1年前
ision (楼主) 1年前
wang22 1年前
don178 (作者) 1年前
讨论数量: 12

那不然呢,每次循环分配一次内存??forr 每次循环会重新赋值给 stu ,所以 stu的地址不会变,但这个地址存的数据会变。

1年前 评论
Alone88 1年前
ision (楼主) 1年前
wang22 1年前
don178 (作者) 1年前

如果不适用指针的话,内容就会变

1年前 评论
ision (楼主) 1年前
ision (楼主) 1年前

引用问题的吧,几个存的都是引用stu,最后一个赋值后,前面的3个就同时更新为最后一个了

1年前 评论

issue: github.com/golang/go/discussions/5... 确切的说这是go的一个bug,go的团队也想解决这个问题,但是承诺了go1向下兼容性,所以这个问题迟迟没有解决,后期可能会在go.mod中加参数来解决这个问题,现阶段的解决办法就是在循环中用一个临时变量接受 for _, stu := range stus { stu := stu}

1年前 评论

range在迭代中会做值拷贝,会把整个结构体拷贝给stu变量,stu内存地址不改变,所以输出的三个地址是一样的,三次拷贝的内容会在stu地址上覆盖,因此最后map中3个键都指向的是最后一次拷贝的内容。
如果用"for i := 0; i < len(stus); i++{}",就不会出现这种情况了

1年前 评论

牛的,我也是遇到这个问题,看到各位的解释,才恍然大悟

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!