我正在尝试构建一个新的结构列表,其中包含对另一个切片中存在的项的引用。如果你看到它会更容易理解,所以我准备了一个可以运行的片段。我有一个由两个点(笛卡尔坐标(组成的列表(dummylist
(,我想解析它来构建一个包含具有一些特征(在本例中,X>80(的项目的新列表(mylist
(。我定义了两个点:{X:90.00,Y:50.00}和{X:20.00,Y:30.0}。我预计mylist将包含{X:90.0,Y:50.0},而在末尾有{X:20.0,Y:30.0}。通过在这里和那里打印一些内容,我可以验证算法运行良好(在正确的情况下,它进入"if"条件(,但在末尾;mylist";包含错误的元素。
package main
import(
"fmt"
)
func main() {
type point struct {
X float64
Y float64
}
type pointsList []point
type pointContainer struct {
Point *point
}
type pointContainerList []pointContainer
// Prepare a slice with two elements
dummylist := new(pointsList)
*dummylist = append(*dummylist, point{X:90.0, Y:50.0})
*dummylist = append(*dummylist, point{X:20.0 , Y:30.0})
// My empty list
mylist := new(pointContainerList)
fmt.Println(fmt.Sprintf("---- At the beginning, mylist contains %d points", len(*mylist)))
// Filter the initial list to take only elements
for _, pt := range *dummylist {
fmt.Println("n---- Evaluating point ", pt)
if pt.X > 80 {
fmt.Println("Appending", pt)
*mylist = append(*mylist, pointContainer{Point: &pt})
fmt.Println("Inserted point:", (*mylist)[0].Point, "len = ", len(*mylist))
}
}
// mylist should contain {X:90.0, Y:50.0}, instead...
fmt.Println(fmt.Sprintf("n---- At the end, mylist contains %d points", len(*mylist)))
fmt.Println("Content of mylist:", (*mylist)[0].Point)
}
您可以在这里运行代码:https://play.golang.org/p/AvrC3JJBLdT
一些有益的考虑因素:我已经通过多个测试看到,在最后,mylist包含循环中最后一个解析的项。我认为参考文献有问题。这就像如果列表中插入的项目(在第一次迭代中(依赖于";pt";其他迭代。相反,如果我使用索引(for i, pt := range *dummylist
和(*dummylist)[i]
(,一切都可以正常工作。
在谈论果朗的虫子之前。。。我是不是错过了什么?
是的,您遗漏了一些内容。在线:
*mylist = append(*mylist, pointContainer{Point: &pt})
您正在将循环变量&pt
的地址放入您的结构中。随着循环的继续,pt
的值会发生变化。(或者换一种说法,&pt
将是循环每次迭代的相同指针(。
入门语言规范:
。。。
迭代值被分配给相应的迭代赋值语句中的变量。
迭代变量可以由";范围";子句使用短变量声明的形式(:=(。在这种情况下,它们的类型是设置为相应迭代值的类型,其范围为";对于";陈述它们在每次迭代中被重复使用。如果迭代变量是在";对于";陈述执行之后,它们的值将是上一次迭代的值。
一个解决方案是创建一个新的值,但我不确定你从这么多指针中得到了什么:[]point
可能比指向point
s的指针的一段结构的指针更有效(也不容易出错(。