Reputation: 2111
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
Upvotes: 5
Views: 3794
Reputation: 8490
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.
Upvotes: 0
Reputation: 42413
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.
Upvotes: 12
Reputation: 6844
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).
Upvotes: 3