一道golang中关于for range常见坑的面试题

以下代码运行,会输出什么?

package main

import "fmt"

type student struct {
	Name string
	Age  int
}

func pase_student() {
	m := make(map[string]*student)
	stus := []student{
		{Name: "A", Age: 1},
		{Name: "B", Age: 2},
		{Name: "C", Age: 3},
	}
	for _, stu := range stus {
		m[stu.Name] = &stu
	}

	for k, v := range m {
		fmt.Printf("%v,%v,%v\n", k, v.Name, v.Age)
	}
}


func main() {
	pase_student()
}

请思考,答案在文末
























答案

A,C,3
B,C,3
C,C,3

为什么?

因为在golangfor range中,临时变量stu会被复用,然后将新的值复制进去,而不会另开辟空间。所以题目中m[stu.Name] = &stu,会导致stu中的值会是最后一次复制进去的值,即stus最后一个值。

我们可以写个测试程序,验证这个“坑”:

func main() {

	a := []int{1, 2, 3, 4}

	for x, n := range a {
		fmt.Printf("%d: %d\n", x, n)
		fmt.Printf("%p\n", &n)
	}
}

输出

0: 1
0xc0000160c8
1: 2
0xc0000160c8
2: 3
0xc0000160c8
3: 4
0xc0000160c8

可以看到,每次&n都是固定的

如何修改?

第1种,使用值,而不是指针。可以将 m := make(map[string]*student) 改成 m := make(map[string]student) , 完整代码如下:


func pase_student() {
	m := make(map[string]student)
	stus := []student{
		{Name: "A", Age: 1},
		{Name: "B", Age: 2},
		{Name: "C", Age: 3},
	}
	for _, stu := range stus {
		m[stu.Name] = stu
	}

	for k, v := range m {
		fmt.Printf("%v,%v,%v\n", k, v.Name, v.Age)
	}
}

第2种,不用for range改用经典的for

func pase_student() {
	m := make(map[string]student)
	stus := []student{
		{Name: "A", Age: 1},
		{Name: "B", Age: 2},
		{Name: "C", Age: 3},
	}
	for i := 0; i < len(stus); i++ {
		m[stus[i].Name] = stus[i]
	}

	for k, v := range m {
		fmt.Printf("%v,%v,%v\n", k, v.Name, v.Age)
	}
}

其他方式也可以。

所以,在实际项目开发中,用到for range时赋值时一定要注意这个“坑”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值