Search code examples
pointersgostructlanguage-lawyercomposite-literals

Go struct literals, why is this one addressable?


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?


Solution

  • 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.