我正在尝试构建一个新的结构列表,其中包含对另一个切片中存在的项目的引用。如果你看到它更容易理解,所以我准备了一个你可以运行的代码片段。我有一个包含两个点(笛卡尔坐标)的列表()dummylist,我想对其进行解析以构建一个新列表(mylist我定义了两点:{X:90.0, Y:50.0} 和 {X:20.0 , Y:30.0}。我希望 mylist 将包含 {X:90.0, Y:50.0},而不是最后有 {X:20.0, Y:30.0}。通过到处打印,我可以验证算法是否正常工作(它在正确的情况下进入“if”条件),但最后,“mylist”包含错误的元素。package mainimport( "fmt")func main() {type point struct { X float64 Y float64}type pointsList []pointtype pointContainer struct { Point *point}type pointContainerList []pointContainer// Prepare a slice with two elementsdummylist := new(pointsList)*dummylist = append(*dummylist, point{X:90.0, Y:50.0})*dummylist = append(*dummylist, point{X:20.0 , Y:30.0})// My empty listmylist := new(pointContainerList)fmt.Println(fmt.Sprintf("---- At the beginning, mylist contains %d points", len(*mylist)))// Filter the initial list to take only elementsfor _, 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]),一切正常。在谈论 Golang 中的错误之前......我错过了什么吗?
1 回答
眼眸繁星
TA贡献1873条经验 获得超9个赞
是的,你错过了一些东西。在这条线上:
*mylist = append(*mylist, pointContainer{Point: &pt})
您将循环变量的地址&pt
放入您的结构中。随着循环的继续,值的pt
变化。(或者换句话说,&pt
循环的每次迭代都将是相同的指针)。
来自go 语言规范:
...
迭代值被分配给各个迭代变量,就像在赋值语句中一样。
迭代变量可以由“范围”子句使用短变量声明 (:=) 的形式来声明。在这种情况下,它们的类型被设置为各自迭代值的类型,它们的范围是“for”语句的块;它们在每次迭代中重复使用。如果迭代变量在“for”语句之外声明,则在执行后它们的值将是最后一次迭代的值。
一种解决方案是创建一个新值,但我不确定您从这么多指针中获得了什么:[]point
可能比指向指向point
s的指针结构切片的指针更有效(并且更不容易出错) .
- 1 回答
- 0 关注
- 115 浏览
添加回答
举报
0/150
提交
取消