I have a struct and a method that's working on the structs reference. The pointer address is changing every time I call the method. Why is it like that?
Code
package main
import "k8s.io/contrib/compare/Godeps/_workspace/src/github.com/emicklei/go-restful/log"
type Whatever struct{
Name string
}
func (whatever *Whatever) GetNameByReference() (string) {
log.Printf("Whatever.GetNameByReference() memory address: %v", &whatever)
return whatever.Name
}
func evaluateMemoryAddressWhenNotWritingAnything() {
whatever := Whatever{}
whatever.GetNameByReference()
whatever.GetNameByReference()
whatever.GetNameByReference()
}
func main() {
evaluateMemoryAddressWhenNotWritingAnything()
}
Output:
log.go:30: Whatever.GetNameByReference() memory address: 0xc420034020
log.go:30: Whatever.GetNameByReference() memory address: 0xc420034030
log.go:30: Whatever.GetNameByReference() memory address: 0xc420034038
Never think and never talk about references. Go has no notion of "reference", everything is a value. Some things are pointer values. Your problem stems from thinking about *X
as "a reference to an X" which it isn't: It is a value holding the memory address of an X
(or nil).
So in func (whatever *Whatever)
the variable whatever
is a pointer to a Whatever
. The value of whatever
is the memory address of the Whatever
the pointer points to. You would like to print this memory address, i.e. the value of whatever
.
You do Printf("%v", &whatever)
. Remember: whatever
is a variable (holding a memory address). So &whatever
is the address of the variable itself: &whatever
is of type **Whatever
. What you find at the address &whatever
is not the value you are interested in; it is just the temporary variable used to store the address of the original Whatever
. Of course this temporary variable is not pinned in memory an may change freely.
You should do Printf("%p", whatever)
. The verb %p
is for pointer values and whatever
is a pointer and you are interested in its value, so print this value.
You are not displaying the address of the struct, you are displaying the address of the address (address of the pointer). The pointer is passed as a parameter and thus new each time. Remove the & in log.Printf("Whatever.GetNameByReference() memory address: %v", &whatever)
to get what you want (and use %p instead of %v).
Calling method
func (whatever *Whatever) GetNameByReference() (string) {
is much the same as calling function providing receiver as first argument
func GetNameByReference(whatever *Whatever) (string) {
Go calling convention is to always pass arguments copy_by_value. So each time you call whatever.GetNameByReference()
it receives fresh copy of whatever
which itself holds same *Whatever
address. As already written doing
log.Printf("Whatever.GetNameByReference() memory address: %v", whatever) //instead of &whatever
will log the same whatever
value which is address.