golang内幕之for-range-value

本文通过几个示例展示了在Go语言中遍历map时可能出现的问题,特别是当尝试复制map的值到另一个map时遇到的地址引用问题。文章提供了具体的解决方法,并解释了Go语言这种行为背后的原因。

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

func ForRangeValue_1() {
	var mapAges map[string]int
	mapAges = make(map[string]int)
	mapAges["name-1"] = 1
	mapAges["name-2"] = 2
	mapAges["name-3"] = 3

	var newAges map[string]*int
	newAges = make(map[string]*int)

	for k, v := range mapAges {
		newAges[k] = &v;
	}

	for k, v := range newAges {
		fmt.Println(k, v, *v)
	}
}

咋看,很想newAges从mapAges拷贝了一份key,value的值,其实不是,运行结果如下:

=== RUN   TestForRangeValue_1
name-1 0xc0000542f0 3
name-2 0xc0000542f0 3
name-3 0xc0000542f0 3
--- PASS: TestForRangeValue_1 (0.00s)
PASS

从结果可以看出newAges的value部分,是个地址值,并且指向了同一地址。按照其他语言,for k,v应该是临时变量,每遍历一次,都会导致产生新的临时变量k,v。但golang没有,下面我们简单验证一下:

func ForRangeValue_2() {
	var mapAges map[string]int
	mapAges = make(map[string]int)
	mapAges["name-1"] = 1
	mapAges["name-2"] = 2
	mapAges["name-3"] = 3

	for k, v := range mapAges {
		fmt.Println(&k, &v, k, v)
	}
}
=== RUN   TestForRangeValue_2
0xc000048550 0xc0000542f0 name-1 1
0xc000048550 0xc0000542f0 name-2 2
0xc000048550 0xc0000542f0 name-3 3
--- PASS: TestForRangeValue_2 (0.00s)
PASS

可以看到,for k,v中每一次遍历中,k和v都指向了一个相同地址,然后每次将map的key和value按照值传递的原则,赋值给k,v。

golang这样做,有他的道理,毕竟带来一定的性能提升。

解决方案:

竟然golang编译器没给我们创建新的变量,那么我们只好自己来生成

func ForRangeValue_3() {
	var mapAges map[string]int
	mapAges = make(map[string]int)
	mapAges["name-1"] = 1
	mapAges["name-2"] = 2
	mapAges["name-3"] = 3

	var newAges map[string]*int
	newAges = make(map[string]*int)

	for k, v := range mapAges {
		var pv int = v
		newAges[k] = &pv
	}

	for k, v := range newAges {
		fmt.Println(k, v, *v)
	}
}
=== RUN   TestForRangeValue_3
name-1 0xc0000542f0 1
name-2 0xc0000542f8 2
name-3 0xc000054300 3
--- PASS: TestForRangeValue_3 (0.00s)
PASS

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值