5

http.HandleFuncルーティングの設定やhtml.templateページをレンダリングするパッケージなどの組み込みのもののみを使用して、go で Web サイトを構築しています。本当に空想的なものは何もなく、うまく機能します。ここで、エラー処理について考え始めました。パニックやその他の問題をキャッチして、静的なエラー ページにリダイレクトしたいと考えています。goでそれを行う最良の方法は何ですか?

私が最初に考えていた強引なアプローチは、エラーが検出されたときにリダイレクトすることですが、一般的なキャッチオールでもいいでしょう。それについてのドキュメントには何も見つかりませんでした。

(同様に 404 についても考えています。)

4

1 に答える 1

8

golang ブログにはエラー処理に関するすばらしい記事があり、特に Web 関連のエラーを最後に取り上げています。

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

基本的に、通常の http ハンドラーを、エラーを返す独自のハンドラーでラップします。ラッパーは、新しいハンドラーがエラーを返すかどうかをチェックし、そうであれば反応します。これに似たものを使用して、recover とも呼びます。これは私が使用するコードのスニペットです (これは無料でオープンです)。

エラー用のカスタム ページはまだ用意していませんが、気になっているので簡単に追加できるはずです。

// 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)
        }
    }
}
于 2012-12-11T15:20:30.767 に答える