考虑the following example并注意指针变量a
的位置如何保持固定,如预期的那样:
var a *int
v1 := 1
v2 := 2
a = &v1
fmt.Printf("%p\n", &a) // output: 0x1040c128
a = &v2
fmt.Printf("%p\n", &a) // output: 0x1040c128
现在考虑以下结构定义:
type foo struct {
bar int
}
如果在this example中将a
声明为foo
的指针变量,则其在内存中的位置不保持不变。
var a *foo
v1 := foo{bar: 1}
v2 := foo{bar: 2}
a = &v1
fmt.Printf("%p\n", a) // output: 0x10414020
a = &v2
fmt.Printf("%p\n", a) // output: 0x10414024
为什么?
答案 0 :(得分:3)
您确定自己没有输入错误并使用fmt.Printf("%p\n", a)
代替fmt.Printf("%p\n", &a)
,因为第一个使用&a
,而您的第二个示例使用a
。
答案很长:
用
fmt.Printf("%p\n", a)
您打印出a
的值,该值是*foo
类型的指针。粗略地说,指针是一个包含内存位置地址的变量。与
a = &v1
您将a
设置为v1
a = &v2
您将a
设置为v2
的地址。 v1
和v2
在内存中有不同的位置,因此当你打印出你的值时,你就会看到它。
如果您使用
var a *foo
v1 := foo{bar: 1}
v2 := foo{bar: 2}
a = &v1
fmt.Printf("%p\n", &a)
a = &v2
fmt.Printf("%p\n", &a)
然后你会看到两次打印相同的号码,因为现在你打印出了a的位置。所以:
a = &v
fmt.Printf("%p\n", a) // prints location of v, not location of a
a = &v
fmt.Printf("%p\n", &a) // prints location of a, not location of v
注:
对于人们称之为指针以及地址是什么,存在一些含糊之处。有人说指针是一个地址,因为它包含一个内存位置的地址"但是指针不是实际上一个内存地址,具体取决于确切的上下文。另外,a
指向b
通常意味着a
是包含b
地址的指针。同样,&v
或者被称为" v"的地址。和"指向v"的指针其中(至少在我看来)是同样正确的,这就是为什么我最初使用"设置一个指向v"的指针。