为什么struct引用的内存地址会发生变化?

时间:2017-01-18 08:41:03

标签: pointers go struct reference pass-by-reference

我有一个结构和方法正在处理结构参考。每次调用方法时指针地址都在变化。为什么会那样?

代码

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()
}

输出:

log.go:30: Whatever.GetNameByReference() memory address: 0xc420034020
log.go:30: Whatever.GetNameByReference() memory address: 0xc420034030
log.go:30: Whatever.GetNameByReference() memory address: 0xc420034038

3 个答案:

答案 0 :(得分:10)

永远不要思考,也不要谈论参考文献。 Go没有"引用"的概念,一切都是值。有些东西是指针值。你的问题源于考虑*X和#34;对X"它不是:它是一个保存X(或零)的内存地址的值。

因此,在func (whatever *Whatever)中,变量whatever是指向Whatever的指针。 whatever的值是指针指向的Whatever的内存地址。您想打印此内存地址,即whatever的值。

你做Printf("%v", &whatever)。请记住:whatever是一个变量(保存内存地址)。因此&whatever是变量本身的地址:&whatever的类型为**Whatever。你在地址&whatever找到的是你感兴趣的价值;它只是用于存储原始Whatever地址的临时变量。当然,这个临时变量没有固定在内存中,可能会自由改变。

你应该Printf("%p", whatever)。动词%p用于指针值,whatever是指针,您对其值感兴趣,因此请打印此值。

答案 1 :(得分:3)

您没有显示结构的地址,您正在显示地址的地址(指针的地址)。指针作为参数传递,因此每次都是新的。删除&在log.Printf("Whatever.GetNameByReference() memory address: %v", &whatever)中获取您想要的内容(并使用%p代替%v)。

答案 2 :(得分:0)

通话方法

func (whatever *Whatever) GetNameByReference() (string) {

与调用函数提供接收器作为第一个参数

非常相似
func GetNameByReference(whatever *Whatever) (string) {

Go调用约定总是传递参数copy_by_value。因此,每当您致电whatever.GetNameByReference()时,它都会收到whatever的新副本,该副本本身拥有相同的*Whatever地址。正如已写的那样做

log.Printf("Whatever.GetNameByReference() memory address: %v", whatever) //instead of &whatever

将记录相同的whatever地址值。