2015-02-26 21 views
8

Tôi muốn tạo trình xử lý lỗi toàn cục để gửi nó qua email.Trình xử lý khôi phục toàn cầu cho golang http panic

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

Làm thế nào để làm cho nó toàn cầu. Sẽ dễ dàng nếu tôi biết lỗi nào sẽ xảy ra

if err != nil { 
sendMeMail(err) 
} 

Nhưng phải làm gì trong trường hợp tôi không biết chính xác một lỗi xảy ra ở đâu? Vì vậy, tôi nên thêm một trình xử lý ish toàn cầu recover. Nhưng làm thế nào để làm điều đó chính xác tôi không biết.

Cập nhật

tôi thêm defer recover đến đầu main nhưng nó không bao giờ thực thi trên yêu cầu http://localhost:3001. Vì vậy, hoảng loạn không được gửi qua email.

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

Trả lời

20

Bạn có thể quấn xử lý của bạn trong một middleware phục hồi

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 
} 

Bạn có thể mất một nhìn vào codahale recovery handler hoặc negroni middleware để biết thêm chi tiết.

+1

e.Error() phải là err.Error()? –

+0

cố định @eyeAppsLLC. – tarrsalah

+0

thực sự thích giải pháp, hoạt động cho tôi :) – Danie

Các vấn đề liên quan