函数接收器的地址因方法而异

I have the following code. https://play.golang.org/p/YAa6cgtA3Vo

The address of the receiver pointer varies between method calls. This is perplexing. Can anyone explain why this is the case? Do I need to pass a pointer to a receiver as an argument in order to maintain the same address?

type myStruct struct {
    //struct content is irrelevant
}

func (ptrToStruct *myStruct) returnAddress() **myStruct {
    return &ptrToStruct
}

func (ptrToStruct *myStruct) method1() {
    addressOfPtr := ptrToStruct.returnAddress()
    fmt.Println(&ptrToStruct)
    fmt.Println(addressOfPtr)
    if &ptrToStruct != addressOfPtr {
        fmt.Println("Different addresses!")
    }
}

EDIT:

What I want is the address of ptrToStruct and not its value. I know that I could just get it in method1() by typing addressOfPtr = &ptrToStruct but in my use case I have some logic happening in the returnAddress() method and I need it to come from there.

That's simple: when you have var ms myStruct somewhere, calling ms.returnAddress() would pass the address of the ms variable to returnAddress, and that address would always be the same (this is easily verifyable — try it itself).

Now consider that the ptrToStruct in the returnAddress definition is just a special argument to be passed to that method, and it has a concrete type — *myStruct.

This type internally is just an integer — large enough to store an address of any memory location on your platform/OS combination.

Now consider that when the call ms.returnAddress() is performed, the address of the ms variable is taken and written to the ptrToStruct argument passed to returnAddress. And that argument is also a variable — with the lifetime equal to the duration of the function call, and visible only in that function's body.

This variable is automatically created on the call stack by the code which prepares the function call. (And the same happens to all the other method arguments.)

So, when you take the address of ptrToStuct, you take the address of a variable appeared at some location on the call stack which will be gone once the method returns.

Now consider that:

  • goroutine stacks in Go are growable (and hence may be relocated in memory when grown);
  • a method may be called from different goroutines (each has its own stack);
  • even if the method is called from the same goroutine multiple times, it may be called from different places in the code path executed by that goroutine.

All of the above may lead to the address of ptrToStruct variable being essentially random from call to call.

What you (probably) actually want is just returning the value of ptrToStruct as is, not its address.

If you feel like not really getting into how ptrToStruct springs into existence and vanishes, consider starting with this.