Go中的 for range 结合 & 取地址的趣味小问题

本文探讨了Golang中forrange与地址符&结合的编程问题,展示了为何map值并非预期,深入剖析了拷贝行为并给出了解决方案。通过实例和内存地址分析,揭示了如何正确使用forrange避免此类意外结果。
摘要由CSDN通过智能技术生成

前言

在网上发现一道golang 中的 for range& 取地址结合的题目,感觉很有趣,先来看看演示代码。

演示代码

package main

import "fmt"

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)
	}
}

输出结果:

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

是不是很惊愕,结果为什么不是预期的,map的值都是一个呢?

原因分析

for range 每次产生的 keyvalue 其实是对应的 stus 里面值的拷贝,不是对应的 stus 里面的值的引用,所以出现了这种问题。

stustusfor循环中申请的一个局部变量,每次循环都会拷贝 stus 中对应的值 stu。迭代遍历之后,stu 每次会被重新赋值,而在 m 这个 map 中记录的 value 只不过是 stu内存地址

我可以打印一下 &stu 的内存地址:

... ...

for _, stu := range stus {
		fmt.Printf("%p\n",&stu)
		m[stu.name] = &stu
	}

... ...

输出内存地址如下:

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

会发现所有的内存地址都是一样的

解决方案

重新申请一个变量,即可解决

... ...

for _, stu := range stus {
		s := stu
		m[stu.name] = &s
	}

... ...

输出内存地址如下:

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

注意:

修改后,这里输出的结果每次运行结果都不一样,因为 map 数据是无序的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汀风说后端

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值