2015-02-26 27 views
8

Desidero creare un gestore di errori globale per inviarlo via e-mail.gestore globale di recupero per il panico http golan

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

Come renderlo globale. Sarebbe facile se so dove si verificherà l'errore

if err != nil { 
sendMeMail(err) 
} 

Ma cosa fare nei casi in cui non so esattamente dove si verificherà un errore? Quindi dovrei aggiungere un gestore di risorse globali recover. Ma come farlo esattamente non lo so.

Aggiornamento

ho aggiunto defer recover a inizio main ma non è mai esegue su richiesta http://localhost:3001. Quindi il panico non viene inviato via 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") 
} 

risposta

20

Puoi avvolgere i gestori in una ripresa 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 
} 

Potete dare un'occhiata a codahale recovery handler o negroni middleware per maggiori dettagli.

+1

e.Error() dovrebbe essere err.Error()? –

+0

corretto @eyeAppsLLC. – tarrsalah

+0

piace molto alla soluzione, funziona per me :) – Danie

Problemi correlati