I faced an issue today and was able to find it and fix it quickly but do not fully understand why golang semantic is like that.
I'm using Go 1.10.
package main
import "fmt"
type T struct {
V int
}
var testT = T{}
func main() {
t := &(*(&testT))
t.V = 4
fmt.Println(t, testT) // test.V == t.V -> t == &testT
t1 := &testT
t2 := *t1
t3 := &t2
t3.V = 5
fmt.Println(t3, testT) // t3.V == 4 and test.T == 4 -> t3 != &testT
}
&{4} {4}
&{5} {4}
I was expecting not to be equals to &testT so have the same semantics as with t3, but instead I see that &(*(&)) sequence do not have the same semantic if I store intermediary results in variables
What is the reason for that behaviour?
When you do this:
t1 := &testT
t2 := *t1
t3 := &t2
t3.V = 5
You take the address of testT
, store it in t1
. Then in the next line a new, distinct variable t2
is created which will have a different memory space and address than that of t1
or testT
. Then t3
will store the address of this new, distinct variable, which is independent of t1
or testT
.
When you do this:
t := &(*(&testT))
You take the address of testT
, then you dereference the pointer (you get testT
"back"), then you again take the address of this value which will be the address of testT
, there is no new variable created. So t
will point to testT
.
This is normal and logical, nothing surprising is in it. Relevant section from the spec: Address operators:
For an operand
x
of pointer type*T
, the pointer indirection*x
denotes the variable of typeT
pointed to byx
.
So &testT
is the address of the variable testT
, and *(&testT)
will give you back the testT
variable. Taking its address again will be identical to &testT
.
What may hint against this is taking the address of a composite literal. Spec: Composite literals:
Taking the address of a composite literal generates a pointer to a unique variable initialized with the literal's value.
When you take the address of a composite literal (e.g. &image.Point{}
), that does create a new, anonymous variable under the hood, and the address of that anonymous variable will be the result of the expression. But taking the address of a variable does not create a new variable.