From: Russ Cox x.f
is illegal.
x
is of pointer or interface type and has the value
-nil
, assigning to, evaluating, or calling x.f
+If x
is of pointer type and has the value
+nil
and x.f
denotes a struct field,
+assigning to or evaluating x.f
+causes a run-time panic.
+x
is of interface type and has the value
+nil
, calling or
+evaluating the method x.f
causes a run-time panic.
f := T.Mv
, f
is invoked
as f(t, 7)
not t.f(7)
.
To construct a function that binds the receiver, use a
-closure.
+function literal or
+method value.
@@ -3442,6 +3451,111 @@ It is legal to derive a function value from a method of an interface type. The resulting function takes an explicit receiver of that interface type.
+
+If the expression x
has static type T
and
+M
is in the method set of type T
,
+x.M
is called a method value.
+The method value x.M
is a function value that is callable
+with the same arguments as a method call of x.M
.
+The expression x
is evaluated and saved during the evaluation of the
+method value; the saved copy is then used as the receiver in any calls,
+which may be executed later.
+
+The type T
may be an interface or non-interface type.
+
+As in the discussion of method expressions above,
+consider a struct type T
with two methods,
+Mv
, whose receiver is of type T
, and
+Mp
, whose receiver is of type *T
.
+
+type T struct { + a int +} +func (tv T) Mv(a int) int { return 0 } // value receiver +func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver + +var t T +var pt *T +func makeT() T ++ +
+The expression +
+ ++t.Mv ++ +
+yields a function value of type +
+ ++func(int) int ++ +
+These two invocations are equivalent: +
+ ++t.Mv(7) +f := t.Mv; f(7) ++ +
+Similarly, the expression +
+ ++pt.Mp ++ +
+yields a function value of type +
+ ++func(float32) float32 ++ +
+As with selectors, a reference to a non-interface method with a value receiver
+using a pointer will automatically dereference that pointer: pt.Mv
is equivalent to (*pt).Mv
.
+
+As with method calls, a reference to a non-interface method with a pointer receiver
+using an addressable value will automatically take the address of that value: t.Mv
is equivalent to (&t).Mv
.
+
+f := t.Mv; f(7) // like t.Mv(7) +f := pt.Mp; f(7) // like pt.Mp(7) +f := pt.Mv; f(7) // like (*pt).Mv(7) +f := t.Mp; f(7) // like (&t).Mp(7) +f := makeT().Mp // invalid: result of makeT() is not addressable ++ +
+Although the examples above use non-interface types, it is also legal to create a method value +from a value of interface type. +
+ ++var i interface { M(int) } = myVal +f := i.M; f(7) // like i.M(7) ++