【golang】for range中取地址操作的陷阱

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/idwtwt/article/details/87378419

Tips:for range创建了每个元素的副本,而不是直接返回每个元素的引用

例子1:

package main

import "fmt"

func main() {
	slice := []int{0, 1, 2, 3}
	myMap := make(map[int]*int)

	for index, value := range slice {
		myMap[index] = &value
	}
	fmt.Println("=====new map=====")
	prtMap(myMap)
}

func prtMap(myMap map[int]*int) {
	for key, value := range myMap {
		fmt.Printf("map[%v]=%v\n", key, *value)
	}
}

输出:

dotzdeMacBook-Pro-2:src dotz$ ./range 
=====new map=====
map[0]=3
map[1]=3
map[2]=3
map[3]=3

例子2:

package main  
  
import "fmt"  
  
type Test struct {
    name string
}

func (this *Test) Point() { // this  为指针
    fmt.Println(this.name)
}


  
func main() {  
    ts := []Test{{"a"}, {"b"}, {"c"}}
    for _, t := range ts {
        defer t.Point() //输出 c c c
    }

} 

输出:

dotzdeMacBook-Pro-2:src dotz$ ./method 
c
c
c

例子1 我们预期输出0,1,2,3,例子2 我们预期输出a,b, c,但两个例子的输出都不是我们预期的。

对于例子1,比较明显,执行了取地址操作,每次都取value变量的地址,所以最后map中的所有元素的值都是value变量的地址(引用),因为最后value被赋值为3,所有输出都是3.

对于例子2,隐晦一点,夹杂了defer和方法接收者的规则,但其实也和例子1一样,执行t.Point()时,得到的是t的地址(引用),for结束时,t被赋值为”c“的地址,main函数返回时,都在执行”c“的接收方法Point,所以输出都是”c".

猜你喜欢

转载自blog.csdn.net/idwtwt/article/details/87378419