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

我正在尝试构建一个新的结构列表,其中包含对另一个切片中存在的项目的引用。如果你看到它更容易理解,所以我准备了一个你可以运行的代码片段。我有一个包含两个点(笛卡尔坐标)的列表()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 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]),一切正常。


在谈论 Golang 中的错误之前......我错过了什么吗?


繁星淼淼
浏览 116回答 1
1回答

眼眸繁星

是的,你错过了一些东西。在这条线上:*mylist = append(*mylist, pointContainer{Point: &pt})您将循环变量的地址&pt放入您的结构中。随着循环的继续,值的pt变化。(或者换句话说,&pt循环的每次迭代都将是相同的指针)。来自go 语言规范:...迭代值被分配给各个迭代变量,就像在赋值语句中一样。迭代变量可以由“范围”子句使用短变量声明 (:=) 的形式来声明。在这种情况下,它们的类型被设置为各自迭代值的类型,它们的范围是“for”语句的块;它们在每次迭代中重复使用。如果迭代变量在“for”语句之外声明,则在执行后它们的值将是最后一次迭代的值。一种解决方案是创建一个新值,但我不确定您从这么多指针中获得了什么:[]point可能比指向指向points的指针结构切片的指针更有效(并且更不容易出错) .
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go