Go语言学习之路

81 阅读2分钟

Go语言学习之路

结构体 struct

练习题

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},
	}
	// fmt.Println(&stus)
	for _, stu := range stus {
		fmt.Println(&stu)
		m[stu.name] = &stu
		// 打印出m的具体键和值
		for key, value := range m {
			fmt.Println("Key:", key, "Value:", value)
		}
	}

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

输出结果:

&{小王子 18}
Key: 小王子 Value: &{小王子 18}
&{娜扎 23}
Key: 小王子 Value: &{娜扎 23}
Key: 娜扎 Value: &{娜扎 23}
&{大王八 9000}
Key: 娜扎 Value: &{大王八 9000}
Key: 大王八 Value: &{大王八 9000}
Key: 小王子 Value: &{大王八 9000}
小王子 => 大王八
娜扎 => 大王八
大王八 => 大王八
  • 问题:为什么m的值均为&{大王八 9000}

  • 回答:循环中的stu变量每次迭代时,确实会被重新赋值为切片stus中的不同元素。然而,问题出现在m[stu.name] = &stu这一行代码上。在这行代码中,&stu获取的是stu的地址,而不是它的值。由于stu是一个变量,它的地址在每次迭代时都是相同的。因此,无论stu的值如何变化,&stu始终指向相同的地址。由于m中存储的是指向stu的指针,而不是值的副本,最终m中的所有指针都指向了同一个地址,即最后一次迭代的stu

  • 解决办法:在循环内部创建一个新的变量s来存储stu的副本,并将该副本的地址&s存储到m中,而不是直接使用stu本身的地址。这样,每次迭代都会有一个新的地址被存储到m中,而不是同一个地址。

解决方案:

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},
	}
	// fmt.Println(&stus)
	for _, stu := range stus {
		s := stu // 解决方案:创建stu的副本s
		m[stu.name] = &s
		// 打印出m的具体键和值
		for key, value := range m {
			fmt.Println("Key:", key, "Value:", value)
		}
	}

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

输出结果:

Key: 小王子 Value: &{小王子 18}
Key: 小王子 Value: &{小王子 18}
Key: 娜扎 Value: &{娜扎 23}
Key: 娜扎 Value: &{娜扎 23}
Key: 大王八 Value: &{大王八 9000}
Key: 小王子 Value: &{小王子 18}
娜扎 => 娜扎
大王八 => 大王八
小王子 => 小王子