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

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??



Solution 1:[1]

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

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1