05 Jul 2017 10:39 +0000
预测以下代码的输出:
package main
import "fmt"
type student struct {
Name string
Age int
}
func main() {
m := make(map[string]*student)
students := []student{
{Name: "zhou", Age: 24},
{Name: "li", Age: 23},
{Name: "wang", Age: 22},
}
for _, stu := range students {
m[stu.Name] = &stu
}
fmt.Println(m["li"].Age)
}
实际结果是:
22
这显然不是以上代码的预期结果, 原因在于遍历 students
的过程中, 变量 stu
仅在 for
循环开始时进行了一次内存分配, 在循环过程中依次被赋值为 students
的各个值, 而非在每一次重新声明. 因此, 以指针形式引用 stu
将始终指向同一位置, 这个位置在循环结束时值为 student{"wang", 22}
, 以上代码的输出结果就显而易见了.
清楚原因后, 解决这样的问题就非常简单, 只要在循环体中为每一次循环单独声明一个变量即可:
func main() {
// ...
for _, stu := range students {
temp := stu
m[stu.Name] = &temp
}
}
注意要以传值形式重新声明, 而不是引用形式!
REFERENCE
Golangid: 1080, type: 1, locale: zh-cn
Loading comments...