This section looks at a specific mistake when using a range loop with pointer elements. If we’re not cautious enough, it can lead us to an issue where we reference the wrong elements. Let’s examine this problem and how to fix it.
Before we begin, let’s clarify the rationale for using a slice or map of pointer elements. There are three main cases:
In terms of semantics, storing data using pointer semantics implies sharing the element. For example, the following method holds the logic to insert an element into a cache:
Here, using the pointer semantics implies that the Foo element is shared by both the caller of Put and the Store struct.
Sometimes we already manipulate pointers. Hence, it can be handy to store pointers directly in our collection instead of values.
If we store large structs, and these structs are frequently mutated, we can use pointers instead to avoid a copy and an insertion for each mutation:
Because updateMapPointer accepts a map of pointers, the mutation of the foo field can be done in a single step.
Now it’s time to discuss the common mistake with pointer elements in range loops. We will consider the following two structs:
A Customer struct representing a customer
A Store that holds a map of Customer pointers
The following method iterates over a slice of Customer elements and stores them in the m map:
In this example, we iterate over the input slice using the range operator and store Customer pointers in the map. But does this method do what we expect?
Let’s give it a try by calling it with a slice of three different Customer structs:
Here’s the result of this code if we print the map:
As we can see, instead of storing three different Customer structs, all the elements stored in the map reference the same Customer struct: 3. What have we done wrong?
Iterating over the customers slice using the range loop, regardless of the number of elements, creates a single customer variable with a fixed address. We can verify this by printing the pointer address during each iteration:
Why is this important? Let’s examine each iteration:
During the first iteration, customer references the first element: Customer 1. We store a pointer to a customer struct.
During the second iteration, customer now references another element: Customer 2. We also store a pointer to a customer struct.
Finally, during the last iteration, customer references the last element: Customer 3. Again, the same pointer is stored in the map.
At the end of the iterations, we have stored the same pointer in the map three times (see figure 4.4). This pointer’s last assignment is a reference to the slice’s last element:Customer 3. This is why all the map elements reference the same Customer.
标签:impact,Customer,elements,map,32,customer,using,pointer From: https://www.cnblogs.com/zhangzhihui/p/18023983