Memory Address Reuse when Copying from Golang Slice
A common misunderstanding in Go programming revolves around memory address copying from slices. Consider the following situation:
You have a Model interface and a Region struct that implements it. The interface is implemented on the pointer of the Region struct. You also have a Regions collection, which is a slice of Region objects. You have a method to convert a Regions object into a []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 }
When you run this code, you would expect to get distinct addresses for each Model in the output slice. However, you end up with the first pointer to the Region outputted multiple times.
To resolve this issue, consider the loop variable item in the original method. It is the same for every iteration of the loop, so the resulting slice contains references to the same underlying data.
The working solution, on the other hand, uses i := (*coll)[idx] to create a new variable for each iteration. This ensures that each Model in the output slice has a unique memory address.
For a better understanding, consider the following code snippet:
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]) } }
This code demonstrates that the memory address of v remains the same throughout the loop, while the memory address of coll[i] increases with each iteration. This behavior is due to v being the loop variable, which remains constant, while coll[i] is a new variable for each iteration.
The above is the detailed content of Why Does Copying from a Go Slice Result in Memory Address Reuse, and How Can It Be Fixed?. For more information, please follow other related articles on the PHP Chinese website!