From 6e15683caee9085dfc953c39a49f13ccc9dc1c86 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Wed, 20 Mar 2013 16:54:07 -0400 Subject: [PATCH] spec: define method values Fixes #2280. R=golang-dev, r, bradfitz, iant, andybalholm, gri CC=golang-dev https://golang.org/cl/7816045 --- doc/go_spec.html | 122 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 118 insertions(+), 4 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index eb412f32d7..4c0718f4a9 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -2424,8 +2424,15 @@ expression is illegal. In all other cases, x.f is illegal.
  • -If 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. +
  • +
  • +If x is of interface type and has the value +nil, calling or +evaluating the method x.f causes a run-time panic.
  • @@ -3349,6 +3356,7 @@ type T struct { } 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 @@ -3434,7 +3442,8 @@ the receiver is provided as the first argument to the call. That is, given 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.

    +

    Method values

    + +

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

    Conversions

    -- 2.50.0