]> Cypherpunks repositories - gostls13.git/commitdiff
spec: define method values
authorRuss Cox <rsc@golang.org>
Wed, 20 Mar 2013 20:54:07 +0000 (16:54 -0400)
committerRuss Cox <rsc@golang.org>
Wed, 20 Mar 2013 20:54:07 +0000 (16:54 -0400)
Fixes #2280.

R=golang-dev, r, bradfitz, iant, andybalholm, gri
CC=golang-dev
https://golang.org/cl/7816045

doc/go_spec.html

index eb412f32d7e7d9903ad67d83bfaf4565928acf2a..4c0718f4a9f0095510c63914355939525fb1edc0 100644 (file)
@@ -1,6 +1,6 @@
 <!--{
        "Title": "The Go Programming Language Specification",
-       "Subtitle": "Version of March 15, 2013",
+       "Subtitle": "Version of March 20, 2013",
        "Path": "/ref/spec"
 }-->
 
@@ -2424,8 +2424,15 @@ expression is illegal.
 In all other cases, <code>x.f</code> is illegal.
 </li>
 <li>
-If <code>x</code> is of pointer or interface type and has the value
-<code>nil</code>, assigning to, evaluating, or calling <code>x.f</code>
+If <code>x</code> is of pointer type and has the value
+<code>nil</code> and <code>x.f</code> denotes a struct field,
+assigning to or evaluating <code>x.f</code>
+causes a <a href="#Run_time_panics">run-time panic</a>.
+</li>
+<li>
+If <code>x</code> is of interface type and has the value
+<code>nil</code>, <a href="#Calls">calling</a> or
+<a href="#Method_values">evaluating</a> the method <code>x.f</code>
 causes a <a href="#Run_time_panics">run-time panic</a>.
 </li>
 </ol>
@@ -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
 </pre>
 
@@ -3434,7 +3442,8 @@ the receiver is provided as the first argument to the call.
 That is, given <code>f := T.Mv</code>, <code>f</code> is invoked
 as <code>f(t, 7)</code> not <code>t.f(7)</code>.
 To construct a function that binds the receiver, use a
-<a href="#Function_literals">closure</a>.
+<a href="#Function_literals">function literal</a> or
+<a href="#Method_values">method value</a>.
 </p>
 
 <p>
@@ -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.
 </p>
 
+<h3 id="Method_values">Method values</h3>
+
+<p>
+If the expression <code>x</code> has static type <code>T</code> and
+<code>M</code> is in the <a href="#Method_sets">method set</a> of type <code>T</code>,
+<code>x.M</code> is called a <i>method value</i>.
+The method value <code>x.M</code> is a function value that is callable
+with the same arguments as a method call of <code>x.M</code>.
+The expression <code>x</code> 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.
+</p>
+
+<p>
+The type <code>T</code> may be an interface or non-interface type.
+</p>
+
+<p>
+As in the discussion of <a href="#Method_expressions">method expressions</a> above,
+consider a struct type <code>T</code> with two methods,
+<code>Mv</code>, whose receiver is of type <code>T</code>, and
+<code>Mp</code>, whose receiver is of type <code>*T</code>.
+</p>
+
+<pre>
+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
+</pre>
+
+<p>
+The expression
+</p>
+
+<pre>
+t.Mv
+</pre>
+
+<p>
+yields a function value of type
+</p>
+
+<pre>
+func(int) int
+</pre>
+
+<p>
+These two invocations are equivalent:
+</p>
+
+<pre>
+t.Mv(7)
+f := t.Mv; f(7)
+</pre>
+
+<p>
+Similarly, the expression
+</p>
+
+<pre>
+pt.Mp
+</pre>
+
+<p>
+yields a function value of type
+</p>
+
+<pre>
+func(float32) float32
+</pre>
+
+<p>
+As with <a href="#Selectors">selectors</a>, a reference to a non-interface method with a value receiver
+using a pointer will automatically dereference that pointer: <code>pt.Mv</code> is equivalent to <code>(*pt).Mv</code>.
+</p>
+
+<p>
+As with <a href="#Calls">method calls</a>, a reference to a non-interface method with a pointer receiver
+using an addressable value will automatically take the address of that value: <code>t.Mv</code> is equivalent to <code>(&amp;t).Mv</code>.
+</p>
+
+<pre>
+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
+</pre>
+
+<p>
+Although the examples above use non-interface types, it is also legal to create a method value
+from a value of interface type.
+</p>
+
+<pre>
+var i interface { M(int) } = myVal
+f := i.M; f(7)  // like i.M(7)
+</pre>
+
 <h3 id="Conversions">Conversions</h3>
 
 <p>