From the Calls section of Go spec: https://golang.org/ref/spec#Calls
A method call
x.m()
is valid if the method set of (the type of)x
containsm
and the argument list can be assigned to the parameter list ofm
. Ifx
is addressable and&x
's method set containsm
,x.m()
is shorthand for(&x).m()
My program.
package main
import (
"fmt"
)
func main() {
p := Point{2, 3}
p.FakeScale(10)
fmt.Println(p)
p.RealScale(10)
fmt.Println(p)
}
type Point struct {
x int
y int
}
func (p Point) FakeScale(s int) {
p.x *= s
p.y *= s
}
func (p *Point) RealScale(s int) {
p.x *= s
p.y *= s
}
Here is the output.
{2, 3}
{20, 30}
My question is specifically about this part of the spec.
If
x
is addressable and&x
's method set containsm
,x.m()
is shorthand for(&x).m()
My questions.
- Is the quoted part applicable to
p.FakeScale(10)
? My guess is "No" because althoughp
is addressable,&p
's method set does not containFakeScale
.p
's method set containsFakeScale
because it uses value receiver, butp
's method set does not containFakeScale
, therefore this part of the spec is not applicable top.FakeScale(10)
. Am I correct? - Is the quoted part applicable to
p.RealScale(10)
? My guess is "Yes" becausep
is addressable and&p
's method set containsRealScale
by virtue of it using a pointer receiver. Therefore, this part of the spec is applicable top.RealScale(10)
. Am I correct? - Can you provide an example code where
x.m()
is valid butx
is not addressable, and thus this part of the spec is not applicable?
Hm. Also I begin to doubt my knowledge of English language but I will try to answer.
You quoted 2 sentences from specification.
Back to your question:
You defined 2 methods for 2 types: first - reciever of Point and second - receiver of pointer to Point.
Obviously, shorthand definition for pointer types is not applicable for non-pointer types.
So, you're correct in your questions 1 or 2.
And your third question is in fact question 1: FakeScale is valid method but method with non-pointer type in receiver, so shorthand definition is not applicable.
Unfortunately, language lawyers have to read the entire specification to put a single sentence in context: The Go Programming Language Specification.
For example,
The method set of type Point consists of all methods declared with receiver type Point (FakeScale).
A method call p.FakeScale is valid since the method set of (the type of) p (Point) contains FakeScale and the argument list, (10), can be assigned to the parameter list, (int), of FakeScale.
The method set of type *Point consists of all methods declared with receiver type *Point (RealScale).
Since p is addressable (p is a variable) and &p's method set contains RealScale, p.RealScale() is shorthand for (&p).RealScale().
Also, see my answer to your earlier question: How to invoke a method with pointer receiver after type assertion?.