go map &取值异常

本文通过一个Go语言代码示例,解释了在for循环中使用切片时,由于值拷贝导致的意外结果。通过分析错误原因,指出在将切片元素存入map时,应避免直接引用循环变量,而是创建一个新的变量来保存每次迭代的值,以确保每个map键对应的值正确无误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

type student struct {
	name string
	age  int
}

func main() {
	m := make(map[string]*student)
	stus := []student{
		{name: "小王子", age: 18},
		{name: "娜扎", age: 23},
		{name: "大王八", age: 9000},
	}


	for _, stu := range stus {
		m[stu.name] = &stu
	}
	for k, v := range m {
		fmt.Println(k, "=>", v.name)
	}
}

返回异常值:

娜扎 => 大王八
大王八 => 大王八
小王子 => 大王八

正确应该返回:

娜扎 => 娜扎
大王八 => 大王八
小王子 => 小王子

修改后:

type student struct {
	name string
	age  int
}

func main() {
	m := make(map[string]*student)
	stus := []student{
		{name: "小王子", age: 18},
		{name: "娜扎", age: 23},
		{name: "大王八", age: 9000},
	}


	for _, stu := range stus {
		s := stu
		m[stu.name] = &s
	}
	for k, v := range m {
		fmt.Println(k, "=>", v.name)
	}
}

原因分析:
来看一下for循环输出的结果:

for _, stu := range stus {
	m[stu.name] = &stu
	fmt.Println(m)
}

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

map[小王子:0xc000004078]
map[娜扎:0xc000004078 小王子:0xc000004078]
map[大王八:0xc000004078 娜扎:0xc000004078 小王子:0xc000004078]

小王子
&{大王八 9000}
小王子 => 大王八

娜扎
&{大王八 9000}
娜扎 => 大王八

大王八
&{大王八 9000}
大王八 => 大王八
结果:
可以看到m输出的值中有固定的地址0xc000004078(每个人运行出来的地址会有不同),所以代表m的v值是相同的,
所以0xc000004078这个地址表示的是"大王八 9000"这个值
原因:
for 循环每次产生的 key 和 value 其实是对应的 stus 里面值的拷贝,不是对应的 stus 里面的值的引用,
所以出现了这种问题
原因:
stu 是 stus 在for循环中申请的一个局部变量,每次循环都会拷贝 stus 中对应的值 stu。迭代遍历之后,
stu 每次会被重新赋值,而在 m 这个 map 中记录的 value 只不过是 最后一次拷贝的stu 的内存地址
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值