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
}
Output
&{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
My question
What is the reason for that behaviour?
When you do this:
You take the address of
testT, store it int1. Then in the next line a new, distinct variablet2is created which will have a different memory space and address than that oft1ortestT. Thent3will store the address of this new, distinct variable, which is independent oft1ortestT.When you do this:
You take the address of
testT, then you dereference the pointer (you gettestT"back"), then you again take the address of this value which will be the address oftestT, there is no new variable created. Sotwill point totestT.This is normal and logical, nothing surprising is in it. Relevant section from the spec: Address operators:
So
&testTis the address of the variabletestT, and*(&testT)will give you back thetestTvariable. 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:
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.