Because one
is already of type One
. The instantiation syntax
t := One{}
creates a value of type One
while the form
p := &One{}
creates a pointer to a value of type One
.
This means that nothing is to be done when calling t.PrintValue
as the receiver type (One
) is already the same as the type of t
(One
as well).
When calling p.PrintValue
the compiler automatically converts an addressable variable to its pointer form because the receiver type (One
) is not equal to the type of p
(*One
). So the expression
p.PrintValue()
is converted to
(*p).PrintValue()
There is also a conversion necessary when calling t.AssignValue
as this method has a pointer receiver but we're supplying a value. This is also done automatically by the compiler where possible.
From the spec on calls:
A method call x.m() is valid if the method set of (the type of) x contains m and the argument list can be assigned to the parameter list of m. If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m()
This means the expression
t.AssignValue()
is converted to
(&t).AssignValue()
Note that this is not always possible. For example when returning a value from a function:
func NewOne(s string) One { return One{s} }
NewOne("foo").AssignValue() // Not possible
x := NewOne("foo")
x.AssignValue() // Possible, automatically converted