我在正在研究的项目中遇到问题。我找到了解决方法,但是我不确定为什么我的解决方案有效。我希望对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 }
当我运行此代码时,我最终获得指向该Region的第一个指针,该指针多次输出。因此,如果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 }
这样可以在输出切片中提供两个不同地址的预期输出。
老实说,这似乎是一个范围函数在两次运行之间重用相同内存地址的错误,但我始终认为在这种情况下我会丢失某些内容。
我希望我为您解释得足够好。我很惊讶原来的解决方案没有用。
谢谢!
在您的第一个(无效)示例中,item是循环变量。它的地址不变,只有值。这就是为什么您在输出idx时间内获得相同地址的原因。
item
idx
运行以下代码,查看运行的机制;
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]) } }