github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/doc/articles/error_handling.html (about) 1 <!--{ 2 "Title": "Error Handling and Go", 3 "Template": true 4 }--> 5 6 <p> 7 If you have written any Go code you have probably encountered the built-in 8 <code>error</code> type. Go code uses <code>error</code> values to 9 indicate an abnormal state. For example, the <code>os.Open</code> function 10 returns a non-nil <code>error</code> value when it fails to open a file. 11 </p> 12 13 {{code "/doc/progs/error.go" `/func Open/`}} 14 15 <p> 16 The following code uses <code>os.Open</code> to open a file. If an error 17 occurs it calls <code>log.Fatal</code> to print the error message and stop. 18 </p> 19 20 {{code "/doc/progs/error.go" `/func openFile/` `/STOP/`}} 21 22 <p> 23 You can get a lot done in Go knowing just this about the <code>error</code> 24 type, but in this article we'll take a closer look at <code>error</code> and 25 discuss some good practices for error handling in Go. 26 </p> 27 28 <p> 29 <b>The error type</b> 30 </p> 31 32 <p> 33 The <code>error</code> type is an interface type. An <code>error</code> 34 variable represents any value that can describe itself as a string. Here is the 35 interface's declaration: 36 </p> 37 38 <pre>type error interface { 39 Error() string 40 }</pre> 41 42 <p> 43 The <code>error</code> type, as with all built in types, is 44 <a href="/doc/go_spec.html#Predeclared_identifiers">predeclared</a> in the 45 <a href="/doc/go_spec.html#Blocks">universe block</a>. 46 </p> 47 48 <p> 49 The most commonly-used <code>error</code> implementation is the 50 <a href="/pkg/errors/">errors</a> package's unexported <code>errorString</code> type. 51 </p> 52 53 {{code "/doc/progs/error.go" `/errorString/` `/STOP/`}} 54 55 <p> 56 You can construct one of these values with the <code>errors.New</code> 57 function. It takes a string that it converts to an <code>errors.errorString</code> 58 and returns as an <code>error</code> value. 59 </p> 60 61 {{code "/doc/progs/error.go" `/New/` `/STOP/`}} 62 63 <p> 64 Here's how you might use <code>errors.New</code>: 65 </p> 66 67 {{code "/doc/progs/error.go" `/func Sqrt/` `/STOP/`}} 68 69 <p> 70 A caller passing a negative argument to <code>Sqrt</code> receives a non-nil 71 <code>error</code> value (whose concrete representation is an 72 <code>errors.errorString</code> value). The caller can access the error string 73 ("math: square root of...") by calling the <code>error</code>'s 74 <code>Error</code> method, or by just printing it: 75 </p> 76 77 {{code "/doc/progs/error.go" `/func printErr/` `/STOP/`}} 78 79 <p> 80 The <a href="/pkg/fmt/">fmt</a> package formats an <code>error</code> value 81 by calling its <code>Error() string</code> method. 82 </p> 83 84 <p> 85 It is the error implementation's responsibility to summarize the context. 86 The error returned by <code>os.Open</code> formats as "open /etc/passwd: 87 permission denied," not just "permission denied." The error returned by our 88 <code>Sqrt</code> is missing information about the invalid argument. 89 </p> 90 91 <p> 92 To add that information, a useful function is the <code>fmt</code> package's 93 <code>Errorf</code>. It formats a string according to <code>Printf</code>'s 94 rules and returns it as an <code>error</code> created by 95 <code>errors.New</code>. 96 </p> 97 98 {{code "/doc/progs/error.go" `/fmtError/` `/STOP/`}} 99 100 <p> 101 In many cases <code>fmt.Errorf</code> is good enough, but since 102 <code>error</code> is an interface, you can use arbitrary data structures as 103 error values, to allow callers to inspect the details of the error. 104 </p> 105 106 <p> 107 For instance, our hypothetical callers might want to recover the invalid 108 argument passed to <code>Sqrt</code>. We can enable that by defining a new 109 error implementation instead of using <code>errors.errorString</code>: 110 </p> 111 112 {{code "/doc/progs/error.go" `/type NegativeSqrtError/` `/STOP/`}} 113 114 <p> 115 A sophisticated caller can then use a 116 <a href="/doc/go_spec.html#Type_assertions">type assertion</a> to check for a 117 <code>NegativeSqrtError</code> and handle it specially, while callers that just 118 pass the error to <code>fmt.Println</code> or <code>log.Fatal</code> will see 119 no change in behavior. 120 </p> 121 122 <p> 123 As another example, the <a href="/pkg/encoding/json/">json</a> package specifies a 124 <code>SyntaxError</code> type that the <code>json.Decode</code> function 125 returns when it encounters a syntax error parsing a JSON blob. 126 </p> 127 128 {{code "/doc/progs/error.go" `/type SyntaxError/` `/STOP/`}} 129 130 <p> 131 The <code>Offset</code> field isn't even shown in the default formatting of the 132 error, but callers can use it to add file and line information to their error 133 messages: 134 </p> 135 136 {{code "/doc/progs/error.go" `/func decodeError/` `/STOP/`}} 137 138 <p> 139 (This is a slightly simplified version of some 140 <a href="http://golang.org/s/camjsondecode">actual code</a> 141 from the <a href="http://camlistore.org">Camlistore</a> project.) 142 </p> 143 144 <p> 145 The <code>error</code> interface requires only a <code>Error</code> method; 146 specific error implementations might have additional methods. For instance, the 147 <a href="/pkg/net/">net</a> package returns errors of type 148 <code>error</code>, following the usual convention, but some of the error 149 implementations have additional methods defined by the <code>net.Error</code> 150 interface: 151 </p> 152 153 <pre>package net 154 155 type Error interface { 156 error 157 Timeout() bool // Is the error a timeout? 158 Temporary() bool // Is the error temporary? 159 }</pre> 160 161 <p> 162 Client code can test for a <code>net.Error</code> with a type assertion and 163 then distinguish transient network errors from permanent ones. For instance, a 164 web crawler might sleep and retry when it encounters a temporary error and give 165 up otherwise. 166 </p> 167 168 {{code "/doc/progs/error.go" `/func netError/` `/STOP/`}} 169 170 <p> 171 <b>Simplifying repetitive error handling</b> 172 </p> 173 174 <p> 175 In Go, error handling is important. The language's design and conventions 176 encourage you to explicitly check for errors where they occur (as distinct from 177 the convention in other languages of throwing exceptions and sometimes catching 178 them). In some cases this makes Go code verbose, but fortunately there are some 179 techniques you can use to minimize repetitive error handling. 180 </p> 181 182 <p> 183 Consider an <a href="http://code.google.com/appengine/docs/go/">App Engine</a> 184 application with an HTTP handler that retrieves a record from the datastore and 185 formats it with a template. 186 </p> 187 188 {{code "/doc/progs/error2.go" `/func init/` `/STOP/`}} 189 190 <p> 191 This function handles errors returned by the <code>datastore.Get</code> 192 function and <code>viewTemplate</code>'s <code>Execute</code> method. In both 193 cases, it presents a simple error message to the user with the HTTP status code 194 500 ("Internal Server Error"). This looks like a manageable amount of code, but 195 add some more HTTP handlers and you quickly end up with many copies of 196 identical error handling code. 197 </p> 198 199 <p> 200 To reduce the repetition we can define our own HTTP <code>appHandler</code> 201 type that includes an <code>error</code> return value: 202 </p> 203 204 {{code "/doc/progs/error3.go" `/type appHandler/`}} 205 206 <p> 207 Then we can change our <code>viewRecord</code> function to return errors: 208 </p> 209 210 {{code "/doc/progs/error3.go" `/func viewRecord/` `/STOP/`}} 211 212 <p> 213 This is simpler than the original version, but the <a 214 href="/pkg/net/http/">http</a> package doesn't understand functions that return 215 <code>error</code>. 216 To fix this we can implement the <code>http.Handler</code> interface's 217 <code>ServeHTTP</code> method on <code>appHandler</code>: 218 </p> 219 220 {{code "/doc/progs/error3.go" `/ServeHTTP/` `/STOP/`}} 221 222 <p> 223 The <code>ServeHTTP</code> method calls the <code>appHandler</code> function 224 and displays the returned error (if any) to the user. Notice that the method's 225 receiver, <code>fn</code>, is a function. (Go can do that!) The method invokes 226 the function by calling the receiver in the expression <code>fn(w, r)</code>. 227 </p> 228 229 <p> 230 Now when registering <code>viewRecord</code> with the http package we use the 231 <code>Handle</code> function (instead of <code>HandleFunc</code>) as 232 <code>appHandler</code> is an <code>http.Handler</code> (not an 233 <code>http.HandlerFunc</code>). 234 </p> 235 236 {{code "/doc/progs/error3.go" `/func init/` `/STOP/`}} 237 238 <p> 239 With this basic error handling infrastructure in place, we can make it more 240 user friendly. Rather than just displaying the error string, it would be better 241 to give the user a simple error message with an appropriate HTTP status code, 242 while logging the full error to the App Engine developer console for debugging 243 purposes. 244 </p> 245 246 <p> 247 To do this we create an <code>appError</code> struct containing an 248 <code>error</code> and some other fields: 249 </p> 250 251 {{code "/doc/progs/error4.go" `/type appError/` `/STOP/`}} 252 253 <p> 254 Next we modify the appHandler type to return <code>*appError</code> values: 255 </p> 256 257 {{code "/doc/progs/error4.go" `/type appHandler/`}} 258 259 <p> 260 (It's usually a mistake to pass back the concrete type of an error rather than 261 <code>error</code>, 262 for reasons discussed in <a href="/doc/go_faq.html#nil_error">the Go FAQ</a>, 263 but it's the right thing to do here because <code>ServeHTTP</code> is the only 264 place that sees the value and uses its contents.) 265 </p> 266 267 <p> 268 And make <code>appHandler</code>'s <code>ServeHTTP</code> method display the 269 <code>appError</code>'s <code>Message</code> to the user with the correct HTTP 270 status <code>Code</code> and log the full <code>Error</code> to the developer 271 console: 272 </p> 273 274 {{code "/doc/progs/error4.go" `/ServeHTTP/` `/STOP/`}} 275 276 <p> 277 Finally, we update <code>viewRecord</code> to the new function signature and 278 have it return more context when it encounters an error: 279 </p> 280 281 {{code "/doc/progs/error4.go" `/func viewRecord/` `/STOP/`}} 282 283 <p> 284 This version of <code>viewRecord</code> is the same length as the original, but 285 now each of those lines has specific meaning and we are providing a friendlier 286 user experience. 287 </p> 288 289 <p> 290 It doesn't end there; we can further improve the error handling in our 291 application. Some ideas: 292 </p> 293 294 <ul> 295 <li>give the error handler a pretty HTML template, 296 <li>make debugging easier by writing the stack trace to the HTTP response when 297 the user is an administrator, 298 <li>write a constructor function for <code>appError</code> that stores the 299 stack trace for easier debugging, 300 <li>recover from panics inside the <code>appHandler</code>, logging the error 301 to the console as "Critical," while telling the user "a serious error 302 has occurred." This is a nice touch to avoid exposing the user to inscrutable 303 error messages caused by programming errors. 304 See the <a href="defer_panic_recover.html">Defer, Panic, and Recover</a> 305 article for more details. 306 </ul> 307 308 <p> 309 <b>Conclusion</b> 310 </p> 311 312 <p> 313 Proper error handling is an essential requirement of good software. By 314 employing the techniques described in this post you should be able to write 315 more reliable and succinct Go code. 316 </p>