This is all about use and assignment of values vs pointers.
In both cases, m[something]
holds an address to a data
.
However, the important distinction is what d1
and d2
are.
d1 is of type *data
:
The value of d1
is a pointer. When we assign &data{...}
to d1
, this changes the value of d1
to be a pointer to the new struct.
Since you are assigning, or changing the value of d1
, the map still holds the old value.
d1 := &data{1}
fmt.Printf("d1 value: %p
", d1)
// d1 value: 0x10410020
d1 = &data{2}
fmt.Printf("d1 value: %p
", d1)
// d1 value: 0x10410024
As you can see: the address in memory that d1
is pointing to has changed. You are storing the value 0x10410020
in the map, so even if you change p1
to point to another address, the pointer inside the map still points to the original location.
The pointers look like:
m["d1"] -----> data{1}
d1 -----> data{2}
d2 is of type data
:
In the case of d2
, you are storing the address of the variable d2
. On assignment, we change the value of d2
, but its address does not change.
d2 := data{1}
fmt.Printf("d2 address: %p
", &d2)
// d2 address: 0x10410028
d2 = data{2}
fmt.Printf("d2 address: %p
", &d2)
// d2 address: 0x10410028
Since this address 0x10410028
is what you are storing in the map, it is pointing to the value of d2
which changes on assignment.
The pointers in this look like (they're both pointers to the same area of memory. Sorry, it's hard to draw arrows in ascii):
m["d2"] -----\
data{2}
d2 -----/