复制一个带指针的列表到另一个列表

huangapple go评论81阅读模式
英文:

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])
}

huangapple
  • 本文由 发表于 2017年2月7日 03:12:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/42075480.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定