【发布时间】:2015-04-28 15:45:59
【问题描述】:
我正在处理的项目中遇到问题。我找到了解决方法,但我不确定为什么我的解决方案有效。我希望有人对 Go 指针的工作方式有更多经验可以帮助我。
我有一个 Model 接口和一个实现该接口的 Region 结构。 Model 接口是在 Region 结构的指针上实现的。我还有一个 Regions 集合,它是 Region 对象的一部分。我有一个方法可以将 Regions 对象转换为 []Model:
// 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 函数在运行之间重用相同内存地址的错误,但我总是认为在这种情况下我会遗漏一些东西。
我希望我已经为您解释得足够好。我很惊讶原来的解决方案不起作用。
谢谢!
【问题讨论】:
-
旁注,您几乎从不想使用指向切片的指针(即您的
coll *Regions,实际上是*[]Region)。 Slices 很小并且已经包含指向数据的指针。唯一需要为Regions使用指针接收器的情况是您需要更改方法中的长度和/或容量。