This question already has an answer here:
For these two struct
type A struct {
Number *int
}
type B struct {
Number int
}
If I want to loop on slice of B and assign the value of B.Number to new 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)
}
}
I will found that all aSlice a.Number is the same value and same pointer.
for _, v := range aSlice {
fmt.Printf("aSlice Value %v Pointer %v
", *v.Number,v.Number)
}
Will print
aSlice Value 3 Pointer 0x10414020
aSlice Value 3 Pointer 0x10414020
aSlice Value 3 Pointer 0x10414020
So does range only update the value of _,v in for loop and doesn't change the pointer ?
Full Code : https://play.golang.org/p/2wopH9HOjwj
</div>
It occurred because variable v
is created at the beginning of the loop and doesn't change. So, every element in aSlice
has a pointer to the same variable. You should write this:
for _, v := range bSlice {
a := A{}
v := v
a.Number = &v.Number
aSlice = append(aSlice, a)
}
Here you create at every iteration new variable with its own pointer.
As @Adrian stated This has nothing to do with memory. The A
struct is actually contains a pointer to integer value.
type A struct {
Number *int
}
So when you are assigning the value from bSlice
to A
struct and then appending the A
struct in aSlice
which is of A
struct type. It will append the values as it is supposed to do inside Golang.
But you are changing the value at address pointed by A
struct. And initialed with a new value in each iteration which changes the value at that address.
a.Number = &v.Number // here a.Number points to the same address
Hence the aSlice contains the value of last updated integer which is 3
. Since aSlice is a slice of A struct it contains the value inside A struct which is 3
.
But if you do not create a pointer to int
inside A
struct
type A struct {
Number int
}
you will get the output as expected with different address now as.
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
", v.Number, &v.Number)
fmt.Printf(" a Value %v Pointer %v
", a.Number, &a.Number)
}
fmt.Println("
----After Assignment----")
fmt.Printf("%+v
", aSlice)
for i, _ := range aSlice {
fmt.Println(aSlice[i].Number)
}
}
Working Code on Go playground
In Golang spec It is defined for composite Literals as :
Taking the address of a composite literal generates a pointer to a unique variable initialized with the literal's value.
type Point3D struct { x, y, z float64 }
var pointer *Point3D = &Point3D{y: 1000}