Commit 1e8e14c9 authored by Robert Griesemer's avatar Robert Griesemer

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