I have simplified the problem incredibly to a small runnable example of my issue, shown below:
package main
import "fmt"
type A struct {
Name string
}
func main() {
main_list := []A{A{"1"}, A{"b"}, A{"3"}}
second_list := make([]*A, 0)
fmt.Println("FIRST LIST:")
for _, x := range main_list {
fmt.Println(x.Name)
second_list = append(second_list, &x)
}
fmt.Println("SECOND LIST:")
for _, x := range second_list {
fmt.Println((*x).Name)
}
}
Which provides:
FIRST LIST:
1
b
3
SECOND LIST:
3
3
3
The simple task is creating main_list
with some dummy structs. The real issue is creating references (pointers) from the values in main_list
into second_list
. I absolutely do not want copies of the structs, only pointers/references to the main_list
structs. The second for loop iterates through the newly populated second_list
and shows only the last value from main_list
(3
in this example) three times.
I expect the issue arrises with the way I am using &x
in the first loop. With the way I get all three values of second_list
to all be the same struct instance; I am going to assume that I actually made a pointer to the for-loop's iterator (as if it were a reference?). So all the pointers in second_list
will always be the last item referenced in the first loop.
The question: How could I make a pointer from what x
was pointing to at that moment in the for loop?
You're adding the address of the same x
in every call to append
.
You could initialize a new x
and copy the value:
for _, x := range main_list {
x := x
second_list = append(second_list, &x)
}
Or create a new x
directly indexing the slice:
for i := range main_list {
x := main_list[i]
second_list = append(second_list, &x)
}
Or if you want the address of the original value in the slice, you can use:
for i := range main_list {
second_list = append(second_list, &main_list[i])
}