Skip to content

Instantly share code, notes, and snippets.

@smithjessk
Created September 28, 2016 21:51
Show Gist options
  • Save smithjessk/508a39c76ad5c24e4a308c5b9b4de651 to your computer and use it in GitHub Desktop.
Save smithjessk/508a39c76ad5c24e4a308c5b9b4de651 to your computer and use it in GitHub Desktop.
Three separate ways of errors in a `http.Handler`
package main
import (
"encoding/json"
"net/http"
)
type request struct {
ID string
}
type user struct {
ID string
}
// IMO, bad for a handler b/c it is verbose and obfuscates the steps taken in
// this handler.
func withIfStatements(w http.ResponseWriter, r *http.Request) {
req := request{}
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&req)
if err != nil {
handleError(w, err, http.StatusBadRequest)
return
}
value, err := lookup(req.ID)
if err != nil {
handleError(w, err, http.StatusBadRequest)
return
}
err = update(value)
if err != nil {
handleError(w, err, http.StatusInternalServerError)
return
}
writeOKResponse(w)
}
// Better. optionalPanic only panics if err != nil. The status code and error
// are wrapped in some struct, and this handler is in something that recovers.
func withOptioanlPanics(w http.ResponseWriter, r *http.Request) {
req := request{}
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&req)
optionalPanic(err, http.StatusBadRequest)
value, err := lookup(req.ID)
optionalPanic(err, http.StatusBadRequest)
err = update(value)
optionalPanic(err, http.StatusInternalServerError)
writeOKResponse(w)
}
// Best. Maybe?
func withComposability(w http.ResponseWriter, r *http.Request) {
user := user{}
PassRequest(http.StatusBadRequest, func() error {
req := request{}
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&req)
return err
}).PassRequest(http.StatusBadRequest, func() error {
result, err := lookup(req.ID)
user := result
return err
}).Pass(http.StatusInternalServerError, func() error {
return update(user)
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment