当我在玩闭包时,我偶然发现了这种行为。我无法绕过它。
此代码片段有效:
func main(){
var a string = "foo"
var b *string
var c string = "bar"
b = &c
fmt.Printf("%s %s\n", a, *b)
a = "hello"
*b = "world"
fmt.Printf("%s %s\n", a, *b)
}
而这不会:
func main(){
var a string = "foo"
var b *string
*b = "bar"
fmt.Printf("%s %s\n", a, *b)
a = "hello"
*b = "world"
fmt.Printf("%s %s\n", a, *b)
}
https://play.golang.org/p/NHw3X__Wtd
请比我更聪明的人解释一下。
最佳答案
如果您没有明确指定初始值,每个变量都会被初始化为其类型的 zero value。所有指针类型的零值是 nil
这意味着它不指向任何东西(还)。
您可以随时为指针类型的变量分配地址(指针值)。但是,在您初始化指针变量(指向 nil
以外的任何内容)之前,它什么都不指向,因此您无法将任何内容分配给它指向的位置(因为那是“无”)。
为了设置指向的值,首先初始化它,这样它实际上会指向你可以设置/更改的地方。这个初始化可能是一些其他变量的地址(与指向类型相同的类型 - 称为元素类型),或者由内置 new()
函数返回的指向类型的一些新分配的零值的地址。
这条线
var b *string
只是创建了一个
b
类型的新变量 *string
,但它没有指定任何初始值,因此 b
将被初始化为 nil
。它不指向任何东西(或任何地方)。如果您尝试设置指向值:var b *string
*b = "bar"
您会遇到运行时 panic :
panic: runtime error: invalid memory address or nil pointer dereference
为了能够设置指向值,您需要使用非
nil
指针值对其进行初始化,例如:b = new(string)
在此之后,您现在可以设置指向值:
*b = "world"
请注意,当您执行以下操作时:
var b *string
var c string = "bar"
b = &c
这将创建一个
b
类型的变量 *string
,它将获得零值 nil
。并创建一个 c
类型的变量 string
,并用值 "bar"
初始化它。然后获取 c
的地址并将其存储在指针变量 b
中。现在,如果你修改 b
指向的值,那将“也”修改变量 c
的值,因为 b
指向 c
(或者更准确地说 b
存储 c
所在的内存地址)。因此,如果在此之后您执行以下操作:*b = "world"
然后打印
c
和 *b
的值,两者都是 "world"
:fmt.Println(c, *b) // Prints "world world"
关于pointers - Go 指针第一次赋值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38019680/