Go struct literals,为什么这个是可寻址的?

Go struct literals, why is this one addressable?

我正在看书"The Go Programming Language"。这对我们(相当)有经验的程序员来说非常好,并解释了其他语言的交叉点之间的差异——但我发现了一个我不完全理解的案例。

我对 C++ 非常了解,而且我知道 Go 调用(C++ 中的调用)rvalues/xvalues "non-addressable"。只有"variables" [GOPL的话]是可寻址的。

好的,很公平;有道理。

因此,例如,这是非法的(根据第一次印刷的第 159 页)

Point{1, 2}.ScaleBy(2) // compile error: can't take address of Point literal

因为 (*Point).ScaleBy*Point 作为接收参数,而 Point 文字是不可寻址的。

(如果你还没有读过这本书,Point 是一个包含字段 X, Y float64 的结构体。

但是,在第 162 页,我们有

type ColoredPoint struct {
    *Point
    Color color.RGBA
}

p := ColoredPoint(&Point{1, 1}, red)
// ...more code ...

这显然是有效的并且可以编译。

问题:

为什么第二种情况下的 Point 文字是可寻址的?

这是为了方便而特例,还是我遗漏了一些大局?

为了方便起见,这是一个特例。规范提到了异常 here.

As an exception to the addressability requirement, x may also be a (possibly parenthesized) composite literal.

为 Mellow Marmot 的回答添加更多细节:

Spec: Variables:

Calling the built-in function new or taking the address of a composite literal allocates storage for a variable at run time. Such an anonymous variable is referred to via a (possibly implicit) pointer indirection.

Point{1, 1}是一个复合字面量,获取它的地址会在底层创建一个匿名变量,表达式的结果就是这个匿名变量的地址。

因此,正如您从技术上看到的那样,它是一个 变量 被寻址,因此它不违反这一点:

Only "variables" [GOPL's words] are addressable.

另请查看此答案,了解您还可以执行哪些其他 "goodies" 或技巧:

&T{} 表示法在第 4.4.1 节“结构文字”第 103 页中进行了解释:

Because structs are so commonly dealt with through pointers, it’s possible to use this shorthand notation to create and initialize a struct variable and obtain its address:

pp := &Point{1, 2}

It is exactly equivalent to

pp := new(Point)
*pp = Point{1, 2}

but &Point{1, 2} can be used directly within an expression, such as a function call.

很高兴您喜欢这本书。