github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/doc/articles/defer_panic_recover.html (about) 1 <!--{ 2 "Title": "Defer, Panic, and Recover", 3 "Template": true 4 }--> 5 6 <p> 7 Go has the usual mechanisms for control flow: if, for, switch, goto. It also 8 has the go statement to run code in a separate goroutine. Here I'd like to 9 discuss some of the less common ones: defer, panic, and recover. 10 </p> 11 12 <p> 13 A <b>defer statement</b> pushes a function call onto a list. The list of saved 14 calls is executed after the surrounding function returns. Defer is commonly 15 used to simplify functions that perform various clean-up actions. 16 </p> 17 18 <p> 19 For example, let's look at a function that opens two files and copies the 20 contents of one file to the other: 21 </p> 22 23 {{code "/doc/progs/defer.go" `/func CopyFile/` `/STOP/`}} 24 25 <p> 26 This works, but there is a bug. If the call to os.Create fails, the 27 function will return without closing the source file. This can be easily 28 remedied by putting a call to src.Close before the second return statement, 29 but if the function were more complex the problem might not be so easily 30 noticed and resolved. By introducing defer statements we can ensure that the 31 files are always closed: 32 </p> 33 34 {{code "/doc/progs/defer2.go" `/func CopyFile/` `/STOP/`}} 35 36 <p> 37 Defer statements allow us to think about closing each file right after opening 38 it, guaranteeing that, regardless of the number of return statements in the 39 function, the files <i>will</i> be closed. 40 </p> 41 42 <p> 43 The behavior of defer statements is straightforward and predictable. There are 44 three simple rules: 45 </p> 46 47 <p> 48 1. <i>A deferred function's arguments are evaluated when the defer statement is 49 evaluated.</i> 50 </p> 51 52 <p> 53 In this example, the expression "i" is evaluated when the Println call is 54 deferred. The deferred call will print "0" after the function returns. 55 </p> 56 57 {{code "/doc/progs/defer.go" `/func a/` `/STOP/`}} 58 59 <p> 60 2. <i>Deferred function calls are executed in Last In First Out order 61 </i>after<i> the surrounding function returns.</i> 62 </p> 63 64 <p> 65 This function prints "3210": 66 </p> 67 68 {{code "/doc/progs/defer.go" `/func b/` `/STOP/`}} 69 70 <p> 71 3. <i>Deferred functions may read and assign to the returning function's named 72 return values.</i> 73 </p> 74 75 <p> 76 In this example, a deferred function increments the return value i <i>after</i> 77 the surrounding function returns. Thus, this function returns 2: 78 </p> 79 80 {{code "/doc/progs/defer.go" `/func c/` `/STOP/`}} 81 82 <p> 83 This is convenient for modifying the error return value of a function; we will 84 see an example of this shortly. 85 </p> 86 87 <p> 88 <b>Panic</b> is a built-in function that stops the ordinary flow of control and 89 begins <i>panicking</i>. When the function F calls panic, execution of F stops, 90 any deferred functions in F are executed normally, and then F returns to its 91 caller. To the caller, F then behaves like a call to panic. The process 92 continues up the stack until all functions in the current goroutine have 93 returned, at which point the program crashes. Panics can be initiated by 94 invoking panic directly. They can also be caused by runtime errors, such as 95 out-of-bounds array accesses. 96 </p> 97 98 <p> 99 <b>Recover</b> is a built-in function that regains control of a panicking 100 goroutine. Recover is only useful inside deferred functions. During normal 101 execution, a call to recover will return nil and have no other effect. If the 102 current goroutine is panicking, a call to recover will capture the value given 103 to panic and resume normal execution. 104 </p> 105 106 <p> 107 Here's an example program that demonstrates the mechanics of panic and defer: 108 </p> 109 110 {{code "/doc/progs/defer2.go" `/package main/` `/STOP/`}} 111 112 <p> 113 The function g takes the int i, and panics if i is greater than 3, or else it 114 calls itself with the argument i+1. The function f defers a function that calls 115 recover and prints the recovered value (if it is non-nil). Try to picture what 116 the output of this program might be before reading on. 117 </p> 118 119 <p> 120 The program will output: 121 </p> 122 123 <pre>Calling g. 124 Printing in g 0 125 Printing in g 1 126 Printing in g 2 127 Printing in g 3 128 Panicking! 129 Defer in g 3 130 Defer in g 2 131 Defer in g 1 132 Defer in g 0 133 Recovered in f 4 134 Returned normally from f.</pre> 135 136 <p> 137 If we remove the deferred function from f the panic is not recovered and 138 reaches the top of the goroutine's call stack, terminating the program. This 139 modified program will output: 140 </p> 141 142 <pre>Calling g. 143 Printing in g 0 144 Printing in g 1 145 Printing in g 2 146 Printing in g 3 147 Panicking! 148 Defer in g 3 149 Defer in g 2 150 Defer in g 1 151 Defer in g 0 152 panic: 4 153 154 panic PC=0x2a9cd8 155 [stack trace omitted]</pre> 156 157 <p> 158 For a real-world example of <b>panic</b> and <b>recover</b>, see the 159 <a href="/pkg/encoding/json/">json package</a> from the Go standard library. 160 It decodes JSON-encoded data with a set of recursive functions. 161 When malformed JSON is encountered, the parser calls panic to unwind the 162 stack to the top-level function call, which recovers from the panic and returns 163 an appropriate error value (see the 'error' and 'unmarshal' methods of 164 the decodeState type in 165 <a href="/src/pkg/encoding/json/decode.go">decode.go</a>). 166 </p> 167 168 <p> 169 The convention in the Go libraries is that even when a package uses panic 170 internally, its external API still presents explicit error return values. 171 </p> 172 173 <p> 174 Other uses of <b>defer</b> (beyond the file.Close example given earlier) 175 include releasing a mutex: 176 </p> 177 178 <pre>mu.Lock() 179 defer mu.Unlock()</pre> 180 181 <p> 182 printing a footer: 183 </p> 184 185 <pre>printHeader() 186 defer printFooter()</pre> 187 188 <p> 189 and more. 190 </p> 191 192 <p> 193 In summary, the defer statement (with or without panic and recover) provides an 194 unusual and powerful mechanism for control flow. It can be used to model a 195 number of features implemented by special-purpose structures in other 196 programming languages. Try it out. 197 </p>