spec: clarify returns, defer statements, and panics

This is an attempt at making the interaction between
these three constructs clearer. Specifically:

- return statements terminate a function, execute deferred
  functions, return to the caller, and then execution
  continues after the call

- panic calls terminate a function, execute deferred
  functions, return to the caller, and then re-panic

- deferred functions are executed before a function _returns_
  to its caller

The hope is that with this change it becomes clear when a
deferred function is executed (when a function returns),
and when it is not (when a program exits).

R=r, rsc, iant, ken, iant
CC=golang-dev
https://golang.org/cl/6736071
This commit is contained in:
Robert Griesemer 2012-11-01 10:13:48 -07:00
parent 5c1422afab
commit 1e8e14c901

View file

@ -1,6 +1,6 @@
<!--{
"Title": "The Go Programming Language Specification",
"Subtitle": "Version of October 31, 2012",
"Subtitle": "Version of November 1, 2012",
"Path": "/ref/spec"
}-->
@ -4540,8 +4540,10 @@ select {} // block forever
<h3 id="Return_statements">Return statements</h3>
<p>
A "return" statement terminates execution of the containing function
and optionally provides a result value or values to the caller.
A "return" statement in a function <code>F</code> terminates the execution
of <code>F</code>, and optionally provides one or more result values.
Any functions <a href="#Defer_statements">deferred</a> by <code>F</code>
are executed before <code>F</code> returns to its caller.
</p>
<pre class="ebnf">
@ -4611,7 +4613,10 @@ func (devnull) Write(p []byte) (n int, _ error) {
</ol>
<p>
Regardless of how they are declared, all the result values are initialized to the zero values for their type (§<a href="#The_zero_value">The zero value</a>) upon entry to the function.
Regardless of how they are declared, all the result values are initialized to the zero
values for their type (§<a href="#The_zero_value">The zero value</a>) upon entry to the
function. A "return" statement that specifies results sets the result parameters before
any deferred functions are executed.
</p>
<!--
@ -4637,7 +4642,8 @@ BreakStmt = "break" [ Label ] .
If there is a label, it must be that of an enclosing
"for", "switch" or "select" statement, and that is the one whose execution
terminates
<a href="#For_statements">For statements</a>, §<a href="#Switch_statements">Switch statements</a>, §<a href="#Select_statements">Select statements</a>).
<a href="#For_statements">For statements</a>, §<a href="#Switch_statements">Switch statements</a>,
§<a href="#Select_statements">Select statements</a>).
</p>
<pre>
@ -4739,8 +4745,11 @@ FallthroughStmt = "fallthrough" .
<h3 id="Defer_statements">Defer statements</h3>
<p>
A "defer" statement invokes a function whose execution is deferred to the moment
the surrounding function returns.
A "defer" statement invokes a function whose execution is deferred
to the moment the surrounding function returns, either because the
surrounding function executed a <a href="#Return_statements">return statement</a>,
reached the end of its <a href="#Function_declarations">function body</a>,
or because the corresponding goroutine is <a href="#Handling_panics">panicking</a>.
</p>
<pre class="ebnf">
@ -4752,13 +4761,14 @@ The expression must be a function or method call.
Each time the "defer" statement
executes, the function value and parameters to the call are
<a href="#Calls">evaluated as usual</a>
and saved anew but the
actual function is not invoked.
Instead, deferred calls are executed in LIFO order
immediately before the surrounding function returns,
after the return values, if any, have been evaluated and assigned
to the result parameters, but before they
are returned to the caller. For instance, if the deferred function is
and saved anew but the actual function body is not executed.
Instead, deferred functions are executed immediately before
the surrounding function returns, in the reverse order
they were deferred.
</p>
<p>
For instance, if the deferred function is
a <a href="#Function_literals">function literal</a> and the surrounding
function has <a href="#Function_types">named result parameters</a> that
are in scope within the literal, the deferred function may access and modify
@ -5100,21 +5110,16 @@ func recover() interface{}
</pre>
<p>
When a function <code>F</code> calls <code>panic</code>, normal
execution of <code>F</code> stops immediately. Any functions whose
execution was <a href="#Defer_statements">deferred</a> by the
invocation of <code>F</code> are immediately run in the usual way,
but with the current values of any result parameters, and then
<code>F</code> returns to its caller without executing the rest of
the function. To the caller, <code>F</code>
then behaves like a call to <code>panic</code>, terminating its own
execution and running deferred functions in the same manner.
This continues until all
functions in the goroutine have ceased execution, in reverse order.
At that point, the program is
terminated and the error condition is reported, including the value of
the argument to <code>panic</code>. This termination sequence is
called <i>panicking</i>.
A <code>panic</code> call in a function <code>F</code> terminates the execution
of <code>F</code>.
Any functions <a href="#Defer_statements">deferred</a> by <code>F</code>
are executed before <code>F</code> returns to its caller. To the caller,
the call of <code>F</code> then behaves itself like a call to <code>panic</code>,
terminating its own execution and running deferred functions in the same manner.
This continues until all functions in the goroutine have ceased execution,
in reverse order. At that point, the program is terminated and the error
condition is reported, including the value of the argument to <code>panic</code>.
This termination sequence is called <i>panicking</i>.
</p>
<pre>