基于go的Web应用程序中的错误页面

时间:2012-12-11 14:46:14

标签: web-applications error-handling go

我们正在构建一个网站,只使用http.HandleFunc之类的内置内容来设置路由,并使用html.template包来呈现网页。没什么好看的,它工作得很好。现在我开始考虑错误处理,并希望捕获恐慌和诸如此类并重定向到静态错误页面。 go的最佳方法是什么?

我一直在思考的蛮力方法是在检测到错误时重定向但是对于通用的catch-all也会很好。我没有在文档中找到任何关于它的内容。

(也考虑沿着相同的404行。)

1 个答案:

答案 0 :(得分:8)

golang博客上有一篇关于错误处理的精彩文章,它特别涵盖了最后的网络相关错误。

http://blog.golang.org/2011/07/error-handling-and-go.html

基本上,您使用自己的常规http处理程序包装可能会返回错误。包装器检查您的新处理程序是否返回错误,如果是这样,则会发生错误。我使用类似于此的东西,我也称之为恢复。这是我使用的代码片段(免费且开放)。

虽然我还没有为错误提供自定义页面,但我一直认为这应该是很容易添加的。

// Error is the expected return of a dae.Handler, or nil otherwise.
type Error struct {
    Error   error
    Code    int
    Message string
}

// NewError is a helper for creating an Error pointer.
func NewError(err error, code int, msg string) *Error {
    return &Error{err, code, msg}
}

// Handler is used to cast functions to its type to implement ServeHTTP.
// Code that panics is automatically recovered and delivers a server 500 error.
type Handler func(http.ResponseWriter, *http.Request) *Error

// NewHandler is a helper to chain multiple functions together.
func New(fn ...Handler) Handler {
    if len(fn) == 0 {
        panic("No Handlers passed in.")
    }

    h := Handler(fn[0])
    for i := 1; i < len(fn); i++ {
        h = h.Add(fn[i])
    }
    return h
}

// ServeHTTP implements the http.Handler interface. If an appHandler returns an
// error, the error is inspected and an appropriate response is written out.
func (fn Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    defer func() {
        if r := recover(); r != nil {
            log.Printf("%v", r)
            http.Error(w, "A serious error has occured.", 500)
            if Debug {
                panic(r.(error))
            }
        }
    }()

    if e := fn(w, r); e != nil {
        log.Printf("Code: %v, Message: \"%s\", Error: %v", e.Code, e.Message, e.Error)
        switch e.Code {
        case 500:
            http.Error(w, e.Message, e.Code)
        case 404:
            http.NotFound(w, r)
            fmt.Fprint(w, e.Message)
        case 200:
            fmt.Fprint(w, e.Message)
        }
    }
}