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>