为什么结构引用的内存地址会改变?
Why does the memory address of a struct reference change?
我有一个结构和一个正在处理结构引用的方法。每次我调用该方法时,指针地址都在变化。为什么会这样?
代码
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
你显示的不是结构的地址,你显示的是地址的地址(指针的地址)。指针作为参数传递,因此每次都是新的。删除 log.Printf("Whatever.GetNameByReference() memory address: %v", &whatever)
中的 & 以获得您想要的内容(并使用 %p 而不是 %v)。
从不思考,从不谈论参考文献。 Go 没有 "reference" 的概念,一切都是值。有些东西是指针值。您的问题源于将 *X
视为 "a reference to an X" 而不是:它是一个保存 X
(或 nil)的内存地址的值。
所以在func (whatever *Whatever)
中变量whatever
是一个指向Whatever
的指针。 whatever
的值是指针指向的Whatever
的内存地址。你想打印这个内存地址,即 whatever
.
的值
你做到了 Printf("%v", &whatever)
。请记住:whatever
是一个变量(保存内存地址)。所以&whatever
是变量本身的地址:&whatever
是**Whatever
类型。您在地址 &whatever
处找到的是 而不是 您感兴趣的值;它只是用于存储原始Whatever
地址的临时变量。当然这个临时变量没有固定在内存中,可以自由更改。
你应该Printf("%p", whatever)
。动词 %p
表示指针值,whatever
是一个指针,您对它的值感兴趣,所以打印这个值。
调用方式
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
值,即地址。
我有一个结构和一个正在处理结构引用的方法。每次我调用该方法时,指针地址都在变化。为什么会这样?
代码
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
你显示的不是结构的地址,你显示的是地址的地址(指针的地址)。指针作为参数传递,因此每次都是新的。删除 log.Printf("Whatever.GetNameByReference() memory address: %v", &whatever)
中的 & 以获得您想要的内容(并使用 %p 而不是 %v)。
从不思考,从不谈论参考文献。 Go 没有 "reference" 的概念,一切都是值。有些东西是指针值。您的问题源于将 *X
视为 "a reference to an X" 而不是:它是一个保存 X
(或 nil)的内存地址的值。
所以在func (whatever *Whatever)
中变量whatever
是一个指向Whatever
的指针。 whatever
的值是指针指向的Whatever
的内存地址。你想打印这个内存地址,即 whatever
.
你做到了 Printf("%v", &whatever)
。请记住:whatever
是一个变量(保存内存地址)。所以&whatever
是变量本身的地址:&whatever
是**Whatever
类型。您在地址 &whatever
处找到的是 而不是 您感兴趣的值;它只是用于存储原始Whatever
地址的临时变量。当然这个临时变量没有固定在内存中,可以自由更改。
你应该Printf("%p", whatever)
。动词 %p
表示指针值,whatever
是一个指针,您对它的值感兴趣,所以打印这个值。
调用方式
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
值,即地址。