m := make(map[int]*int) arr := []int{1, 2, 3, 4, 5} for i, v := range arr { m[i] = &v } for k, v := range m { fmt.Println("k-->v", k, *v) }
运行结果
map是无序的,我们指关注value,value的值都是5,这时候是否有疑问,循环存储了arr,为什么结果都是5
先了解一下range的特性
for range每次都是拷贝原变量的副本,也就是值拷贝
在上面的例子中,我们拷贝并不是 arr[i]对应的地址,而是变量v的地址,v只是一个临时变量
我们修改代码再看
func main() { m := make(map[int]*int) //m1 := make(map[int]*int) arr := []int{1, 2, 3, 4, 5} for i, v := range arr { m[i] = &v fmt.Println(&v) fmt.Println(*m[i]) }
运行结果
0xc0000140d8 1 0xc0000140d8 2 0xc0000140d8 3 0xc0000140d8 4 0xc0000140d8 5
我们可以看到v的地址是不变的,变的是值
所以我们在例1中看到m每次存储的都是v的地址,看下面的代码,我们打印一下m
m := make(map[int]*int) arr := []int{1, 2, 3, 4, 5} for i, v := range arr { m[i] = &v } fmt.Println(m)
运行结果
map[0:0xc0000140d8 1:0xc0000140d8 2:0xc0000140d8 3:0xc0000140d8 4:0xc0000140d8] k-->v 4 5 k-->v 3 5 k-->v 0 5 k-->v 1 5 k-->v 2 5
我们可以看到map元素地址都是一样的
那么就可以解释为什么都是元素都是5了,因为for range最后循环完毕,地址中的值是5,所以我们循环map,里面的值也都是5
例2我们修改切片中的元素添加6,再次运行
m := make(map[int]*int) arr := []int{1, 2, 3, 4, 5, 6} for i, v := range arr { m[i] = &v } fmt.Println(m) for k, v := range m { fmt.Println("k-->v", k, *v) }
map[0:0xc0000140d8 1:0xc0000140d8 2:0xc0000140d8 3:0xc0000140d8 4:0xc0000140d8 5:0xc0000140d8] k-->v 5 6 k-->v 0 6 k-->v 1 6 k-->v 2 6 k-->v 3 6 k-->v 4 6
里面的值都变成6了,这是因为range完毕最后一个值是6,所以循环遍历map只是打印的那个地址里面的值而已
总结for range中value只是一个临时变量,是一个固定的地址,值是不断改变的,而且这个地址只存range完毕的最后一个值
接for和range比较不妨再看一下for循环
func main() { m := make(map[int]*int) m1 := make(map[int]*int) arr := []int{1, 2, 3, 4, 5, 6} for i, v := range arr { m[i] = &v } for i := 0; i < len(arr); i++ { m1[i] = &arr[i] } fmt.Println(m1) fmt.Println(m) for k, v := range m { fmt.Println("m:k-->v", k, *v) } for k, v := range m1 { fmt.Println("m1:k-->v", k, *v) } }
map[0:0xc0000c0060 1:0xc0000c0068 2:0xc0000c0070 3:0xc0000c0078 4:0xc0000c0080 5:0xc0000c0088] map[0:0xc0000aa058 1:0xc0000aa058 2:0xc0000aa058 3:0xc0000aa058 4:0xc0000aa058 5:0xc0000aa058] m:k-->v 0 6 m:k-->v 1 6 m:k-->v 2 6 m:k-->v 3 6 m:k-->v 4 6 m:k-->v 5 6 m1:k-->v 0 1 m1:k-->v 1 2 m1:k-->v 2 3 m1:k-->v 3 4 m1:k-->v 4 5 m1:k-->v 5 6
有不对的地方请指正,蟹蟹!
参考:【golang】 关于for range中只存储最后一个元素的问题 - 要坚持的girl - 博客园