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}
娜扎 => 娜扎
大王八 => 大王八
小王子 => 小王子