Reputation:
I am reading the book "The Go Programming Language". It is very good for us (rather) experienced programmers and explains the differences between the intersection of other languages -- but I've found a case which I do not understand fully.
I know C++ sufficiently good, and I understand that Go calls (what in C++ would be called) rvalues/xvalues "non-addressable". Only "variables" [GOPL's words] are addressable.
OK, fair enough; it makes sense.
And therefore, for instance, this is illegal (according to page 159 in the first printing)
Point{1, 2}.ScaleBy(2) // compile error: can't take address of Point literal
because (*Point).ScaleBy
takes a *Point
as a receiver argument, and a Point
literal is non-addressable.
(If you haven't read the book, Point
is a struct with the fields X, Y float64
.
However, on page 162, we have
type ColoredPoint struct {
*Point
Color color.RGBA
}
p := ColoredPoint(&Point{1, 1}, red)
// ...more code ...
which apparently is valid and will compile.
Question:
Why is the Point
literal in the second case addressable?
Is it a special case for convenience, or am I missing something in the big picture?
Upvotes: 5
Views: 1255
Reputation: 514
The &T{}
notation is explained in Section 4.4.1, Struct Literals, on page 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.
Glad you're otherwise enjoying the book.
Upvotes: 6
Reputation: 417402
Adding a little more detail to Mellow Marmot's answer:
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}
is a composite literal, taking its address will create an anonymous variable under the hood, and the result of the expression will be the address of this anonymous variable.
So as you can see technically it's a variable that is addressed, so it does not violate this:
Only "variables" [GOPL's words] are addressable.
Also check out this answer to see what other "goodies" or tricks you can do: How do I do a literal *int64 in Go?
Upvotes: 2
Reputation: 120931
It's a special case for convenience. The spec mentions the exception here.
As an exception to the addressability requirement, x may also be a (possibly parenthesized) composite literal.
Upvotes: 2