| <!--{ |
| "Title": "Error Handling and Go", |
| "Template": true |
| }--> |
| |
| <p> |
| If you have written any Go code you have probably encountered the built-in |
| <code>error</code> type. Go code uses <code>error</code> values to |
| indicate an abnormal state. For example, the <code>os.Open</code> function |
| returns a non-nil <code>error</code> value when it fails to open a file. |
| </p> |
| |
| {{code "/doc/progs/error.go" `/func Open/`}} |
| |
| <p> |
| The following code uses <code>os.Open</code> to open a file. If an error |
| occurs it calls <code>log.Fatal</code> to print the error message and stop. |
| </p> |
| |
| {{code "/doc/progs/error.go" `/func openFile/` `/STOP/`}} |
| |
| <p> |
| You can get a lot done in Go knowing just this about the <code>error</code> |
| type, but in this article we'll take a closer look at <code>error</code> and |
| discuss some good practices for error handling in Go. |
| </p> |
| |
| <p> |
| <b>The error type</b> |
| </p> |
| |
| <p> |
| The <code>error</code> type is an interface type. An <code>error</code> |
| variable represents any value that can describe itself as a string. Here is the |
| interface's declaration: |
| </p> |
| |
| <pre>type error interface { |
| Error() string |
| }</pre> |
| |
| <p> |
| The <code>error</code> type, as with all built in types, is |
| <a href="/doc/go_spec.html#Predeclared_identifiers">predeclared</a> in the |
| <a href="/doc/go_spec.html#Blocks">universe block</a>. |
| </p> |
| |
| <p> |
| The most commonly-used <code>error</code> implementation is the |
| <a href="/pkg/errors/">errors</a> package's unexported <code>errorString</code> type. |
| </p> |
| |
| {{code "/doc/progs/error.go" `/errorString/` `/STOP/`}} |
| |
| <p> |
| You can construct one of these values with the <code>errors.New</code> |
| function. It takes a string that it converts to an <code>errors.errorString</code> |
| and returns as an <code>error</code> value. |
| </p> |
| |
| {{code "/doc/progs/error.go" `/New/` `/STOP/`}} |
| |
| <p> |
| Here's how you might use <code>errors.New</code>: |
| </p> |
| |
| {{code "/doc/progs/error.go" `/func Sqrt/` `/STOP/`}} |
| |
| <p> |
| A caller passing a negative argument to <code>Sqrt</code> receives a non-nil |
| <code>error</code> value (whose concrete representation is an |
| <code>errors.errorString</code> value). The caller can access the error string |
| ("math: square root of...") by calling the <code>error</code>'s |
| <code>Error</code> method, or by just printing it: |
| </p> |
| |
| {{code "/doc/progs/error.go" `/func printErr/` `/STOP/`}} |
| |
| <p> |
| The <a href="/pkg/fmt/">fmt</a> package formats an <code>error</code> value |
| by calling its <code>Error() string</code> method. |
| </p> |
| |
| <p> |
| It is the error implementation's responsibility to summarize the context. |
| The error returned by <code>os.Open</code> formats as "open /etc/passwd: |
| permission denied," not just "permission denied." The error returned by our |
| <code>Sqrt</code> is missing information about the invalid argument. |
| </p> |
| |
| <p> |
| To add that information, a useful function is the <code>fmt</code> package's |
| <code>Errorf</code>. It formats a string according to <code>Printf</code>'s |
| rules and returns it as an <code>error</code> created by |
| <code>errors.New</code>. |
| </p> |
| |
| {{code "/doc/progs/error.go" `/fmtError/` `/STOP/`}} |
| |
| <p> |
| In many cases <code>fmt.Errorf</code> is good enough, but since |
| <code>error</code> is an interface, you can use arbitrary data structures as |
| error values, to allow callers to inspect the details of the error. |
| </p> |
| |
| <p> |
| For instance, our hypothetical callers might want to recover the invalid |
| argument passed to <code>Sqrt</code>. We can enable that by defining a new |
| error implementation instead of using <code>errors.errorString</code>: |
| </p> |
| |
| {{code "/doc/progs/error.go" `/type NegativeSqrtError/` `/STOP/`}} |
| |
| <p> |
| A sophisticated caller can then use a |
| <a href="/doc/go_spec.html#Type_assertions">type assertion</a> to check for a |
| <code>NegativeSqrtError</code> and handle it specially, while callers that just |
| pass the error to <code>fmt.Println</code> or <code>log.Fatal</code> will see |
| no change in behavior. |
| </p> |
| |
| <p> |
| As another example, the <a href="/pkg/encoding/json/">json</a> package specifies a |
| <code>SyntaxError</code> type that the <code>json.Decode</code> function |
| returns when it encounters a syntax error parsing a JSON blob. |
| </p> |
| |
| {{code "/doc/progs/error.go" `/type SyntaxError/` `/STOP/`}} |
| |
| <p> |
| The <code>Offset</code> field isn't even shown in the default formatting of the |
| error, but callers can use it to add file and line information to their error |
| messages: |
| </p> |
| |
| {{code "/doc/progs/error.go" `/func decodeError/` `/STOP/`}} |
| |
| <p> |
| (This is a slightly simplified version of some |
| <a href="http://golang.org/s/camjsondecode">actual code</a> |
| from the <a href="http://camlistore.org">Camlistore</a> project.) |
| </p> |
| |
| <p> |
| The <code>error</code> interface requires only a <code>Error</code> method; |
| specific error implementations might have additional methods. For instance, the |
| <a href="/pkg/net/">net</a> package returns errors of type |
| <code>error</code>, following the usual convention, but some of the error |
| implementations have additional methods defined by the <code>net.Error</code> |
| interface: |
| </p> |
| |
| <pre>package net |
| |
| type Error interface { |
| error |
| Timeout() bool // Is the error a timeout? |
| Temporary() bool // Is the error temporary? |
| }</pre> |
| |
| <p> |
| Client code can test for a <code>net.Error</code> with a type assertion and |
| then distinguish transient network errors from permanent ones. For instance, a |
| web crawler might sleep and retry when it encounters a temporary error and give |
| up otherwise. |
| </p> |
| |
| {{code "/doc/progs/error.go" `/func netError/` `/STOP/`}} |
| |
| <p> |
| <b>Simplifying repetitive error handling</b> |
| </p> |
| |
| <p> |
| In Go, error handling is important. The language's design and conventions |
| encourage you to explicitly check for errors where they occur (as distinct from |
| the convention in other languages of throwing exceptions and sometimes catching |
| them). In some cases this makes Go code verbose, but fortunately there are some |
| techniques you can use to minimize repetitive error handling. |
| </p> |
| |
| <p> |
| Consider an <a href="http://code.google.com/appengine/docs/go/">App Engine</a> |
| application with an HTTP handler that retrieves a record from the datastore and |
| formats it with a template. |
| </p> |
| |
| {{code "/doc/progs/error2.go" `/func init/` `/STOP/`}} |
| |
| <p> |
| This function handles errors returned by the <code>datastore.Get</code> |
| function and <code>viewTemplate</code>'s <code>Execute</code> method. In both |
| cases, it presents a simple error message to the user with the HTTP status code |
| 500 ("Internal Server Error"). This looks like a manageable amount of code, but |
| add some more HTTP handlers and you quickly end up with many copies of |
| identical error handling code. |
| </p> |
| |
| <p> |
| To reduce the repetition we can define our own HTTP <code>appHandler</code> |
| type that includes an <code>error</code> return value: |
| </p> |
| |
| {{code "/doc/progs/error3.go" `/type appHandler/`}} |
| |
| <p> |
| Then we can change our <code>viewRecord</code> function to return errors: |
| </p> |
| |
| {{code "/doc/progs/error3.go" `/func viewRecord/` `/STOP/`}} |
| |
| <p> |
| This is simpler than the original version, but the <a |
| href="/pkg/net/http/">http</a> package doesn't understand functions that return |
| <code>error</code>. |
| To fix this we can implement the <code>http.Handler</code> interface's |
| <code>ServeHTTP</code> method on <code>appHandler</code>: |
| </p> |
| |
| {{code "/doc/progs/error3.go" `/ServeHTTP/` `/STOP/`}} |
| |
| <p> |
| The <code>ServeHTTP</code> method calls the <code>appHandler</code> function |
| and displays the returned error (if any) to the user. Notice that the method's |
| receiver, <code>fn</code>, is a function. (Go can do that!) The method invokes |
| the function by calling the receiver in the expression <code>fn(w, r)</code>. |
| </p> |
| |
| <p> |
| Now when registering <code>viewRecord</code> with the http package we use the |
| <code>Handle</code> function (instead of <code>HandleFunc</code>) as |
| <code>appHandler</code> is an <code>http.Handler</code> (not an |
| <code>http.HandlerFunc</code>). |
| </p> |
| |
| {{code "/doc/progs/error3.go" `/func init/` `/STOP/`}} |
| |
| <p> |
| With this basic error handling infrastructure in place, we can make it more |
| user friendly. Rather than just displaying the error string, it would be better |
| to give the user a simple error message with an appropriate HTTP status code, |
| while logging the full error to the App Engine developer console for debugging |
| purposes. |
| </p> |
| |
| <p> |
| To do this we create an <code>appError</code> struct containing an |
| <code>error</code> and some other fields: |
| </p> |
| |
| {{code "/doc/progs/error4.go" `/type appError/` `/STOP/`}} |
| |
| <p> |
| Next we modify the appHandler type to return <code>*appError</code> values: |
| </p> |
| |
| {{code "/doc/progs/error4.go" `/type appHandler/`}} |
| |
| <p> |
| (It's usually a mistake to pass back the concrete type of an error rather than |
| <code>error</code>, |
| for reasons discussed in <a href="/doc/go_faq.html#nil_error">the Go FAQ</a>, |
| but it's the right thing to do here because <code>ServeHTTP</code> is the only |
| place that sees the value and uses its contents.) |
| </p> |
| |
| <p> |
| And make <code>appHandler</code>'s <code>ServeHTTP</code> method display the |
| <code>appError</code>'s <code>Message</code> to the user with the correct HTTP |
| status <code>Code</code> and log the full <code>Error</code> to the developer |
| console: |
| </p> |
| |
| {{code "/doc/progs/error4.go" `/ServeHTTP/` `/STOP/`}} |
| |
| <p> |
| Finally, we update <code>viewRecord</code> to the new function signature and |
| have it return more context when it encounters an error: |
| </p> |
| |
| {{code "/doc/progs/error4.go" `/func viewRecord/` `/STOP/`}} |
| |
| <p> |
| This version of <code>viewRecord</code> is the same length as the original, but |
| now each of those lines has specific meaning and we are providing a friendlier |
| user experience. |
| </p> |
| |
| <p> |
| It doesn't end there; we can further improve the error handling in our |
| application. Some ideas: |
| </p> |
| |
| <ul> |
| <li>give the error handler a pretty HTML template, |
| <li>make debugging easier by writing the stack trace to the HTTP response when |
| the user is an administrator, |
| <li>write a constructor function for <code>appError</code> that stores the |
| stack trace for easier debugging, |
| <li>recover from panics inside the <code>appHandler</code>, logging the error |
| to the console as "Critical," while telling the user "a serious error |
| has occurred." This is a nice touch to avoid exposing the user to inscrutable |
| error messages caused by programming errors. |
| See the <a href="defer_panic_recover.html">Defer, Panic, and Recover</a> |
| article for more details. |
| </ul> |
| |
| <p> |
| <b>Conclusion</b> |
| </p> |
| |
| <p> |
| Proper error handling is an essential requirement of good software. By |
| employing the techniques described in this post you should be able to write |
| more reliable and succinct Go code. |
| </p> |