Golang -- range小坑铭记

废话少叙,先上一段代码,猜猜预期的效果。

package main

import (
	"fmt"
)

type student struct {
	Name string
	Age  int
}

func main() {
	m := make(map[string]*student)
	stus := []student{
		{Name: "zhou", Age: 24},
		{Name: "li", Age: 23},
		{Name: "wang", Age: 22},
	}
	for _, stu := range stus {
		m[stu.Name] = &stu
	}

	fmt.Printf("%+v\n", m)

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

  out:

    map[zhou:0x42114e100 li:0x42114e100 wang:0x42114e100]
    k:li v:&{wang 22}
    k:wang v:&{wang 22}
    k:zhou v:&{wang 22}

  是不是很诧异,结果为什么不是预期的,map的值都是一个呢?

  原因:for range每次产生的 k , v 都是一个值拷贝,不是 stus对应值得引用,故而会出现这种结果。

  细节分析:

  for _, stu := range stus {
	m[stu.Name] = &stu
  }

  // stu 是在 for中申请的一个局部变量,地址为:0x42114e100, 每次拷贝stus中对应的值。
  // 迭代遍历之后,stu每次被重新赋值,而map记录的是 变量stu对应的地址值,故而不会产生预期的效果。

  快速解决办法:

    for _, stu := range stus {
	  a := stu
	  m[stu.Name] = &a
     }

  谨在此记录。

posted @ 2017-07-19 17:01  丹江流  阅读(492)  评论(0编辑  收藏  举报