diff options
author | Russ Cox <rsc@golang.org> | 2020-03-09 23:23:49 -0400 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2020-03-11 14:10:22 +0000 |
commit | 7fd29cb024126de10a90c54427e050e7928c54b4 (patch) | |
tree | 42498c25ba0669a5914b2d883419e5d15b7a7a8c /content/defer-panic-and-recover.article | |
parent | 9dd3d9b97af3dba2bd18f1a5e18bd8e8edf78962 (diff) |
content: make spacing consistent + remove comments
Remove repeated blank lines, trailing spaces, trailing blank lines
Remove comments from survey2018.article (only article using them).
Remove blank lines between successive ".commands".
For golang/go#33955.
Change-Id: I90cae37a859a8e39549520569d5f10bc455415d3
Reviewed-on: https://go-review.googlesource.com/c/blog/+/222841
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'content/defer-panic-and-recover.article')
-rw-r--r-- | content/defer-panic-and-recover.article | 35 |
1 files changed, 5 insertions, 30 deletions
diff --git a/content/defer-panic-and-recover.article b/content/defer-panic-and-recover.article index 8bea0ab..2c95aa3 100644 --- a/content/defer-panic-and-recover.article +++ b/content/defer-panic-and-recover.article @@ -12,15 +12,12 @@ 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. - A *defer*statement* 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. - For example, let's look at a function that opens two files and copies the contents of one file to the other: - func CopyFile(dstName, srcName string) (written int64, err error) { src, err := os.Open(srcName) if err != nil { @@ -45,7 +42,6 @@ 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: - func CopyFile(dstName, srcName string) (written int64, err error) { src, err := os.Open(srcName) if err != nil { @@ -67,13 +63,12 @@ guaranteeing that, regardless of the number of return statements in the function the files _will_ be closed. The behavior of defer statements is straightforward and predictable. There are three simple rules: - + 1. _A_deferred_function's_arguments_are_evaluated_when_the_defer_statement_is_evaluated._ - + In this example, the expression "i" is evaluated when the Println call is deferred. The deferred call will print "0" after the function returns. - func a() { i := 0 defer fmt.Println(i) @@ -82,7 +77,7 @@ The deferred call will print "0" after the function returns. } 2. _Deferred_function_calls_are_executed_in_Last_In_First_Out_order_after_the_surrounding_function_returns._ - + This function prints "3210": func b() { @@ -91,9 +86,8 @@ This function prints "3210": } } - 3. _Deferred_functions_may_read_and_assign_to_the_returning_function's_named_return_values._ - + In this example, a deferred function increments the return value i _after_ the surrounding function returns. Thus, this function returns 2: @@ -103,10 +97,8 @@ Thus, this function returns 2: return 1 } - This is convenient for modifying the error return value of a function; we will see an example of this shortly. - *Panic* is a built-in function that stops the ordinary flow of control and begins _panicking_. When the function F calls panic, execution of F stops, any deferred functions in F are executed normally, @@ -118,14 +110,12 @@ Panics can be initiated by invoking panic directly. They can also be caused by runtime errors, such as out-of-bounds array accesses. - *Recover* 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. - Here's an example program that demonstrates the mechanics of panic and defer: package main @@ -158,17 +148,14 @@ Here's an example program that demonstrates the mechanics of panic and defer: g(i + 1) } - 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. - The program will output: - Calling g. Printing in g 0 Printing in g 1 @@ -182,14 +169,11 @@ The program will output: Recovered in f 4 Returned normally from f. - - 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: - Calling g. Printing in g 0 Printing in g 1 @@ -201,12 +185,10 @@ This modified program will output: Defer in g 1 Defer in g 0 panic: 4 - + panic PC=0x2a9cd8 [stack trace omitted] - - For a real-world example of *panic* and *recover*, see the [[https://golang.org/pkg/encoding/json/][json package]] from the Go standard library. @@ -219,25 +201,18 @@ the 'error' and 'marshal' methods of the encodeState type in [[https://golang.or The convention in the Go libraries is that even when a package uses panic internally, its external API still presents explicit error return values. - Other uses of *defer* (beyond the file.Close example given earlier) include releasing a mutex: mu.Lock() defer mu.Unlock() - - printing a footer: - printHeader() defer printFooter() - - and more. - 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 |