dtch60248 2015-02-26 14:58
浏览 147
已采纳

golang http紧急情况的全局恢复处理程序

I want to create global err handler to send it by email.

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")
}

How to make it global. It would be easy if I know where error will occur

if err != nil {
sendMeMail(err)
}

But what to do in cases when I don't know exactly where an error will occur? So I should add a global recoverish handler. But how to do it exactly I don't know.

Update

I added defer recover to beginning of main but it never executes on requesting http://localhost:3001. So panic is not emailed.

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")
}
  • 写回答

2条回答 默认 最新

  • dpx49470 2015-02-26 15:44
    关注

    You can wrap your handlers in a recovery middleware

    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) {
            var err error
            defer func() {
                r := recover()
                if r != nil {
                    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
    }
    

    You can take a a look at codahale recovery handler or negroni middleware for more details.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 微信小程序协议怎么写
  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看