Go中处理带有引用的切片是否存在错误



我正在尝试构建一个新的结构列表,其中包含对另一个切片中存在的项的引用。如果你看到它会更容易理解,所以我准备了一个可以运行的片段。我有一个由两个点(笛卡尔坐标(组成的列表(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可能比指向points的指针的一段结构的指针更有效(也不容易出错(。

最新更新