summaryrefslogtreecommitdiff
path: root/doc/articles/defer_panic_recover.html
diff options
context:
space:
mode:
Diffstat (limited to 'doc/articles/defer_panic_recover.html')
-rw-r--r--doc/articles/defer_panic_recover.html197
1 files changed, 0 insertions, 197 deletions
diff --git a/doc/articles/defer_panic_recover.html b/doc/articles/defer_panic_recover.html
deleted file mode 100644
index c964cd368..000000000
--- a/doc/articles/defer_panic_recover.html
+++ /dev/null
@@ -1,197 +0,0 @@
-<!--{
- "Title": "Defer, Panic, and Recover",
- "Template": true
-}-->
-
-<p>
-Go has the usual mechanisms for control flow: if, for, switch, goto. It also
-has the go statement to run code in a separate goroutine. Here I'd like to
-discuss some of the less common ones: defer, panic, and recover.
-</p>
-
-<p>
-A <b>defer statement</b> pushes a function call onto a list. The list of saved
-calls is executed after the surrounding function returns. Defer is commonly
-used to simplify functions that perform various clean-up actions.
-</p>
-
-<p>
-For example, let's look at a function that opens two files and copies the
-contents of one file to the other:
-</p>
-
-{{code "/doc/progs/defer.go" `/func CopyFile/` `/STOP/`}}
-
-<p>
-This works, but there is a bug. If the call to os.Create fails, the
-function will return without closing the source file. This can be easily
-remedied by putting a call to src.Close before the second return statement,
-but if the function were more complex the problem might not be so easily
-noticed and resolved. By introducing defer statements we can ensure that the
-files are always closed:
-</p>
-
-{{code "/doc/progs/defer2.go" `/func CopyFile/` `/STOP/`}}
-
-<p>
-Defer statements allow us to think about closing each file right after opening
-it, guaranteeing that, regardless of the number of return statements in the
-function, the files <i>will</i> be closed.
-</p>
-
-<p>
-The behavior of defer statements is straightforward and predictable. There are
-three simple rules:
-</p>
-
-<p>
-1. <i>A deferred function's arguments are evaluated when the defer statement is
-evaluated.</i>
-</p>
-
-<p>
-In this example, the expression "i" is evaluated when the Println call is
-deferred. The deferred call will print "0" after the function returns.
-</p>
-
-{{code "/doc/progs/defer.go" `/func a/` `/STOP/`}}
-
-<p>
-2. <i>Deferred function calls are executed in Last In First Out order
-</i>after<i> the surrounding function returns.</i>
-</p>
-
-<p>
-This function prints "3210":
-</p>
-
-{{code "/doc/progs/defer.go" `/func b/` `/STOP/`}}
-
-<p>
-3. <i>Deferred functions may read and assign to the returning function's named
-return values.</i>
-</p>
-
-<p>
-In this example, a deferred function increments the return value i <i>after</i>
-the surrounding function returns. Thus, this function returns 2:
-</p>
-
-{{code "/doc/progs/defer.go" `/func c/` `/STOP/`}}
-
-<p>
-This is convenient for modifying the error return value of a function; we will
-see an example of this shortly.
-</p>
-
-<p>
-<b>Panic</b> is a built-in function that stops the ordinary flow of control and
-begins <i>panicking</i>. When the function F calls panic, execution of F stops,
-any deferred functions in F are executed normally, and then F returns to its
-caller. To the caller, F then behaves like a call to panic. The process
-continues up the stack until all functions in the current goroutine have
-returned, at which point the program crashes. Panics can be initiated by
-invoking panic directly. They can also be caused by runtime errors, such as
-out-of-bounds array accesses.
-</p>
-
-<p>
-<b>Recover</b> is a built-in function that regains control of a panicking
-goroutine. Recover is only useful inside deferred functions. During normal
-execution, a call to recover will return nil and have no other effect. If the
-current goroutine is panicking, a call to recover will capture the value given
-to panic and resume normal execution.
-</p>
-
-<p>
-Here's an example program that demonstrates the mechanics of panic and defer:
-</p>
-
-{{code "/doc/progs/defer2.go" `/package main/` `/STOP/`}}
-
-<p>
-The function g takes the int i, and panics if i is greater than 3, or else it
-calls itself with the argument i+1. The function f defers a function that calls
-recover and prints the recovered value (if it is non-nil). Try to picture what
-the output of this program might be before reading on.
-</p>
-
-<p>
-The program will output:
-</p>
-
-<pre>Calling g.
-Printing in g 0
-Printing in g 1
-Printing in g 2
-Printing in g 3
-Panicking!
-Defer in g 3
-Defer in g 2
-Defer in g 1
-Defer in g 0
-Recovered in f 4
-Returned normally from f.</pre>
-
-<p>
-If we remove the deferred function from f the panic is not recovered and
-reaches the top of the goroutine's call stack, terminating the program. This
-modified program will output:
-</p>
-
-<pre>Calling g.
-Printing in g 0
-Printing in g 1
-Printing in g 2
-Printing in g 3
-Panicking!
-Defer in g 3
-Defer in g 2
-Defer in g 1
-Defer in g 0
-panic: 4
-
-panic PC=0x2a9cd8
-[stack trace omitted]</pre>
-
-<p>
-For a real-world example of <b>panic</b> and <b>recover</b>, see the
-<a href="/pkg/encoding/json/">json package</a> from the Go standard library.
-It decodes JSON-encoded data with a set of recursive functions.
-When malformed JSON is encountered, the parser calls panic to unwind the
-stack to the top-level function call, which recovers from the panic and returns
-an appropriate error value (see the 'error' and 'unmarshal' methods of
-the decodeState type in
-<a href="/src/pkg/encoding/json/decode.go">decode.go</a>).
-</p>
-
-<p>
-The convention in the Go libraries is that even when a package uses panic
-internally, its external API still presents explicit error return values.
-</p>
-
-<p>
-Other uses of <b>defer</b> (beyond the file.Close example given earlier)
-include releasing a mutex:
-</p>
-
-<pre>mu.Lock()
-defer mu.Unlock()</pre>
-
-<p>
-printing a footer:
-</p>
-
-<pre>printHeader()
-defer printFooter()</pre>
-
-<p>
-and more.
-</p>
-
-<p>
-In summary, the defer statement (with or without panic and recover) provides an
-unusual and powerful mechanism for control flow. It can be used to model a
-number of features implemented by special-purpose structures in other
-programming languages. Try it out.
-</p>