先看下下面的代码
package main
import "fmt"
type coder struct {
Name string
Age int
}
func main() {
m := make(map[string]*coder)
coders := []coder{
{Name: "han", Age: 24},
{Name: "li", Age: 24},
{Name: "song", Age: 25},
}
for _, co := range coders {
m[co.Name] = &coder
fmt.Printf("%p\n",&co)
}
for k,v:=range m{
fmt.Printf("%v--->%v\n",k,v)
}
}
运行的结果如下:
0xc42000a1a0
0xc42000a1a0
0xc42000a1a0
song--->&{song 25}
han--->&{song 25}
li--->&{song 25}
我们发现结果m的值只会指向一个值。这样的写法初学者经常会遇到的,很危险! 与Java的foreach一样,都是使用副本的方式。所以m[co.Name]=&stu实际上一致指向同一个指针, 最终该指针的值为遍历的最后一个struct的值拷贝。 就像想修改切片元素的属性:
for _, co:= range coders {
co.Age = co.Age+10
}
这样也是错误的。其正确的做法应该如下:
1.利用for循环,带下标的那种:
for _,co :=range coders{
stu.Age=stu.Age+10
fmt.Println(stus)
}
2.直接用指针数组
m := make(map[string]*coder)
stus := []*coder{
{Name: "han", Age: 24},
{Name: "li", Age: 24},
{Name: "song", Age: 25},
}
for _, co := range coders {
m[stu.Name] = stu
fmt.Printf("%p\n",&stu)
}