Pointers Golang重用从片复制的内存地址?

Pointers Golang重用从片复制的内存地址?,pointers,go,Pointers,Go,我在一个项目中遇到了一个问题。我找到了解决方法,但我不确定我的解决方案为什么有效。我希望有更多的围棋指针工作经验的人能帮助我 我有一个模型接口和一个实现该接口的区域结构。模型接口在区域结构的指针上实现。我还有一个区域集合,它是区域对象的切片。我有一种方法可以将区域对象转换为[]模型: // Regions is the collection of the Region model type Regions []Region // Returns the model collection as

我在一个项目中遇到了一个问题。我找到了解决方法,但我不确定我的解决方案为什么有效。我希望有更多的围棋指针工作经验的人能帮助我

我有一个模型接口和一个实现该接口的区域结构。模型接口在区域结构的指针上实现。我还有一个区域集合,它是区域对象的切片。我有一种方法可以将区域对象转换为[]模型:

// Regions is the collection of the Region model
type Regions []Region

// Returns the model collection as a list of models
func (coll *Regions) ToModelList() []Model {
    output := make([]Model, len(*coll))
    for idx, item := range *coll {
        output[idx] = &item
    }
    return output
}
当我运行这段代码时,第一个指向区域的指针被多次输出。因此,如果Regions集合有两个不同的项,我将得到相同的地址复制两次。当我在切片中设置变量之前打印变量时,它们具有正确的数据

我有点搞砸了,认为Go可能是在循环之间重用内存地址。此解决方案目前在我的测试中适用:

// Returns the model collection as a list of models
func (coll *Regions) ToModelList() []Model {
    output := make([]Model, len(*coll))
    for idx, _ := range *coll {
        i := (*coll)[idx]
        output[idx] = &i
    }
    return output
}
这将在输出片中提供两个不同地址的预期输出

老实说,这似乎是range函数在两次运行之间重用相同内存地址的一个错误,但我总是认为在这种情况下我遗漏了一些东西

我希望我能给你解释清楚。我很惊讶原来的解决方案不起作用

谢谢

在第一个(非工作)示例中,
项是循环变量。它的地址没有改变,只有它的值。这就是为什么在输出
idx
times中得到相同的地址

运行此代码以查看运行中的机制

func main() {

    coll := []int{5, 10, 15}

    for i, v := range coll {
       fmt.Printf("This one is always the same; %v\n", &v)
       fmt.Println("This one is 4 bytes larger each iteration; %v\n", &coll[i])
    }
}

整个循环只有一个
变量,在循环的每次迭代过程中为其分配相应的值。您不会在每次迭代中获得新的
变量。因此,您只是重复地获取同一变量的地址,当然是相同的

另一方面,如果您在循环中声明了一个局部变量,那么它将在每次迭代中成为一个新变量,并且地址将不同:

for idx, item := range *coll {
    temp := item
    output[idx] = &temp
}

我的印象是,由于我在列表中存储指针的引用,Go不应该重用该内存地址。我这样想是不是搞错了?@jnadro52请给我一些来编写一个例子。问题是您要获取项的地址,它只是循环变量。实际上,您想要分配它的值,因为项本身已经是指针了。Go中没有“引用”的概念。“没有错误,根据引用进行思考会导致错误。”evanmcdonnal——这是有道理的。我使用指针的原因是指针接收器实现了模型接口,所以我必须实际使用指针,否则编译器会对我大喊大叫。@Volker-我想我必须对GC如何工作以及Go如何使用这些内存地址做更多的研究。我想你的意思是它只是将指针存储为内存地址,但不把它们当作引用内存。你有什么好的链接来解释它吗?旁注,你几乎不想使用指向切片的指针(即你的
coll*区域
,实际上是
*[]区域
)。很小,并且已经包含指向数据的指针。如果需要更改方法中的长度和/或容量,则只需在
区域使用指针接收器。这是一个非常简洁易懂的描述,谢谢。值得注意的是,创建一个新变量并将其分配给指向该项的指针也不起作用。我也试过了:-)