Pointer receiver method compilation problem: Cannot call a pointer method on 'MyObj{}'

Viewed 573

I have the following method defined:

func (o *MyObj) parse(something string) string {
    // Do stuff
}

This code (1) compiles just fine:

(&MyObj{}).parse(myString)

This code (2) compiles too:

m := MyObj{}
m.parse(myString)

But this code (3) doesn't compile:

MyObj{}.parse(myString)

With the error

Cannot call a pointer method on 'MyObj{}'

My questions:

  1. Why (2) compiles? I read that T method set doesn't include *T method set, hence I'd expect it not to compile.

  2. Given (2) compiles, why wouldn't (3) compile??

1 Answers

The code in (2) m.parse(myString) compiles because calling the method on it equals to addressing and then calling the method on the pointer, i.e. (&m).parse(myString):

If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m()

However this shorthand is not available in (3) MyObj{}.parse(myString) because the literal MyObj{} is not addressable. From the specs: "Address operators":

The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; [...or other cases that don't apply].

And MyObj{} being a composite literal is neither of those; whereas m from example (2) is a variable.

Finally the same section about address operators specifies an exception that explains why the example in (1) (&MyObj{}).parse(myString) compiles:

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

In this case you can take its address, parenthesize it and call the method, which is syntactically similar to the compiler shorthand for (2).

Related