summaryrefslogtreecommitdiff
path: root/doc/articles/error_handling.html
diff options
context:
space:
mode:
Diffstat (limited to 'doc/articles/error_handling.html')
-rw-r--r--doc/articles/error_handling.html316
1 files changed, 0 insertions, 316 deletions
diff --git a/doc/articles/error_handling.html b/doc/articles/error_handling.html
deleted file mode 100644
index 6ba05ac1d..000000000
--- a/doc/articles/error_handling.html
+++ /dev/null
@@ -1,316 +0,0 @@
-<!--{
- "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>