【问题标题】:global recover handler for golang http panicgolang http 恐慌的全局恢复处理程序
【发布时间】:2015-04-29 00:26:53
【问题描述】:

我想创建全局错误处理程序以通过电子邮件发送。

package main

import (
    "github.com/gorilla/mux"
    "log"
    "net/http"
)

func main() {
    rtr := mux.NewRouter()
    rtr.HandleFunc("/", withPanic).Methods("GET")

    http.Handle("/", rtr)
    log.Println("Listening...")

    http.ListenAndServe(":3001", http.DefaultServeMux)
}

func withPanic(w http.ResponseWriter, r *http.Request) {
    panic("somewhere here will be panic, but I don't know where exactly")
}

如何使其全球化。如果我知道哪里会出错就很容易了

if err != nil {
sendMeMail(err)
}

但是,如果我不知道哪里会发生错误,该怎么办?所以我应该添加一个全局recoverish 处理程序。但是具体怎么做我不知道。

更新

我在main 的开头添加了defer recover,但它在请求http://localhost:3001 时从未执行。所以恐慌不会通过电子邮件发送。

package main

import (
    "errors"
    "fmt"
    "github.com/gorilla/mux"
    "log"
    "net/http"
)

func main() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("Recovered in f", r)
            // find out exactly what the error was and set err
            var err error
            switch x := r.(type) {
            case string:
                err = errors.New(x)
            case error:
                err = x
            default:
                err = errors.New("Unknown panic")
            }
            if err != nil {
                // sendMeMail(err)
                fmt.Println("sendMeMail")
            }
        }
    }()
    rtr := mux.NewRouter()
    rtr.HandleFunc("/", withPanic).Methods("GET")

    http.Handle("/", rtr)
    log.Println("Listening...")

    http.ListenAndServe(":3001", http.DefaultServeMux)
}

func withPanic(w http.ResponseWriter, r *http.Request) {
    panic("somewhere here will be panic, but I don't know where exactly")
}

【问题讨论】:

    标签: go gorilla


    【解决方案1】:

    您可以将处理程序包装在恢复中间件中

    package main
    
    import (
        "errors"
        "github.com/gorilla/mux"
        "log"
        "net/http"
    )
    
    func main() {
        m := mux.NewRouter()
        m.Handle("/", RecoverWrap(http.HandlerFunc(handler))).Methods("GET")
    
        http.Handle("/", m)
        log.Println("Listening...")
    
        http.ListenAndServe(":3001", nil)
    
    }
    
    func handler(w http.ResponseWriter, r *http.Request) {
        panic(errors.New("panicing from error"))
    }
    
    func RecoverWrap(h http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            defer func() {
                r := recover()
                if r != nil {
                    var err error
                    switch t := r.(type) {
                    case string:
                        err = errors.New(t)
                    case error:
                        err = t
                    default:
                        err = errors.New("Unknown error")
                    }
                    sendMeMail(err)
                    http.Error(w, err.Error(), http.StatusInternalServerError)
                }
            }()
            h.ServeHTTP(w, r)
        })
    }
    
    func sendMeMail(err error) {
        // send mail
    }
    

    您可以查看codahale recovery handlernegroni middleware 了解更多详情。

    【讨论】:

    • e.Error() 应该是 err.Error()?
    • 固定@eyeAppsLLC。
    • 非常简洁的解决方案
    • r := recover() 从外部函数中隐藏 r *http.Request。如果您想在恢复块中访问它 - 最好更改名称,例如e := recover()
    【解决方案2】:

    我相信这就是gorilla recovery handler 的用途

    【讨论】:

      猜你喜欢
      • 2017-05-07
      • 2015-03-29
      • 1970-01-01
      • 1970-01-01
      • 2019-10-07
      • 1970-01-01
      • 2018-10-28
      • 2015-10-20
      • 2015-09-28
      相关资源
      最近更新 更多