对于这两个结构
type A struct {
Number *int
}
type B struct {
Number int
}
如果我想在B的切片上循环并将B.Number的值分配给新的A.Number
func main() {
aSlice := []A{}
bSlice := []B{B{1}, B{2}, B{3}}
for _, v := range bSlice {
a := A{}
a.Number = &v.Number
aSlice = append(aSlice, a)
}
}
我会发现所有aSlice a.Number都是相同的值和相同的指针。
for _, v := range aSlice {
fmt.Printf("aSlice Value %v Pointer %v\n", *v.Number,v.Number)
}
将打印
aSlice值3指针0x10414020
aSlice值3指针0x10414020
aSlice值3指针0x10414020
那么range是否只更新for循环中的 _,v 的值,并且不更改指针?
答案 0 :(得分:4)
发生这种情况是因为变量v
是在循环开始时创建的,并且没有更改。因此,aSlice
中的每个元素都有一个指向相同变量的指针。您应该这样写:
for _, v := range bSlice {
a := A{}
v := v
a.Number = &v.Number
aSlice = append(aSlice, a)
}
您在每次迭代时都使用自己的指针创建新变量。
答案 1 :(得分:1)
正如@Adrian所说,这与记忆无关。 A
结构实际上包含一个指向整数值的指针。
type A struct {
Number *int
}
因此,当您将bSlice
的值分配给A
结构时,然后将A
的{{1}}结构附加到aSlice
结构类型的A
中。它会像在Golang中那样附加值。
但是您正在更改A
结构所指向的地址处的值。并在每次迭代中以一个新值开头,该值会更改该地址处的值。
a.Number = &v.Number // here a.Number points to the same address
因此,aSlice包含最后更新的整数值3
。由于aSlice是A结构的一个切片,因此它包含A结构内部的值为3
。
但是,如果您没有在int
结构内创建指向A
的指针
type A struct {
Number int
}
您将获得预期的输出,现在使用的地址与此不同。
package main
import (
"fmt"
)
type A struct {
Number int
}
type B struct {
Number int
}
func main() {
aSlice := []A{}
bSlice := []B{B{1}, B{2}, B{3}}
fmt.Println("----Assignment Loop----")
for _, v := range bSlice {
a := A{}
a.Number = v.Number
aSlice = append(aSlice, a)
fmt.Printf("bSlice Value %v Pointer %v\n", v.Number, &v.Number)
fmt.Printf(" a Value %v Pointer %v\n", a.Number, &a.Number)
}
fmt.Println("\n----After Assignment----")
fmt.Printf("%+v\n", aSlice)
for i, _ := range aSlice {
fmt.Println(aSlice[i].Number)
}
}
Go playground上的工作代码
在Golang规范中,它为复合文字定义为:
获取复合文字的地址会生成指向 用文字值初始化的唯一变量。
type Point3D struct { x, y, z float64 }
var pointer *Point3D = &Point3D{y: 1000}