英文:
Duplicating a list to a list with pointers
问题
我已经将问题简化为一个可以运行的小例子,如下所示:
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)
    }
}
运行结果如下:
FIRST LIST:
1
b
3
SECOND LIST:
3
3
3
简单的任务是创建一个带有一些虚构结构体的main_list。真正的问题是从main_list的值创建指向second_list的引用(指针)。我绝对不想要结构体的副本,只想要指向main_list结构体的指针/引用。第二个循环遍历新填充的second_list,并且只显示main_list的最后一个值(在这个例子中是3)三次。
我认为问题出在我在第一个循环中使用&x的方式上。通过这种方式,我得到的second_list中的所有三个值实际上都是对循环变量的指针(就好像它是一个引用?)。因此,second_list中的所有指针始终都指向第一个循环中引用的最后一个项。
问题:我如何才能在循环中创建指向x当前指向的内容的指针?
英文:
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?
答案1
得分: 5
你在每次调用append时都在添加相同的x的地址。
你可以初始化一个新的x并复制其值:
for _, x := range main_list {
    x := x
    second_list = append(second_list, &x)
}
或者直接通过索引创建一个新的x:
for i := range main_list {
    x := main_list[i]
    second_list = append(second_list, &x)
}
或者如果你想要切片中原始值的地址,可以使用:
for i := range main_list {
    second_list = append(second_list, &main_list[i])
}
英文:
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])
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论