当我在玩闭包时,我偶然发现了这种行为。我无法绕过它。

此代码片段有效:

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/

10-14 14:42
查看更多