mirror of https://github.com/golang/go.git
spec: define method values
Fixes #2280. R=golang-dev, r, bradfitz, iant, andybalholm, gri CC=golang-dev https://golang.org/cl/7816045
This commit is contained in:
parent
00224a356a
commit
6e15683cae
122
doc/go_spec.html
122
doc/go_spec.html
|
|
@ -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>(&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>
|
||||
|
|
|
|||
Loading…
Reference in New Issue