一个Golang遍历切片常犯的错误
type Person struct { age int } func f5(arr []Person) []*Person { var personRefSet []*Person for _, person := range arr { personRefSet = append(personRefSet, &person) } return personRefSet } func main() { originArr := []Person{ {age: 1}, {age: 2}, } refArr := f5(originArr) for _, refPerson := range refArr { println(refPerson) } }
输出结果:
0xc0002271c0
0xc0002271c0
从结果来看refArr的每个元素都是相同的。
为了进一步弄清原理,写了以下代码:
func f5(arr []Person) []*Person {
var personRefSet []*Person
for i, person := range arr {
personRefSet = append(personRefSet, &person)
println("get addr by Index:", &arr[i])
println("get temporary object addr by object:", &person)
}
return personRefSet
}
func main() {
originArr := []Person{
{age: 1},
{age: 2},
}
refArr := f5(originArr)
println("-----分割线----")
for i, personRef := range refArr {
println("refArr element(pointer type) value:", personRef)
println("refArr element pointer's addr:", &refArr[i])
}
}
输出:
get addr by Index: 0xc000187f38
get temporary object addr by object: 0xc0002271c0
get addr by Index: 0xc000187f40
get temporary object addr by object: 0xc0002271c0
-----分割线----
refArr element(pointer type) value: 0xc0002271c0
refArr element pointer's addr: 0xc000229120
refArr element(pointer type) value: 0xc0002271c0
refArr element pointer's addr: 0xc000229128
其中:
get addr by Index: 0xc000187f38打印的是通过元素下标获取的元素的地址值
get temporary object addr by object: 0xc0002271c0打印的是当前循环中的临时对象的地址值
refArr element(pointer type) value打印的是遍历的指针变量的值(指针类型比较特殊,它的值就是一个地址值,用这个地址引用或者说存储一个对象)
refArr element pointer's addr打印的是通过下标获取的指针变量的地址
通过这一次探索,对指针和地址值有了新的认识:
地址值是对象在内存中的id,是一个16进制数;
指针是一种变量类型,它保存另一个对象的地址值,指针变量的值就是一个地址值。指针变量自己也是一个对象,也有自己的地址值,理论上就可以套娃,但没有实际意义。
浙公网安备 33010602011771号