將錯誤訊息特別處理

// postToSlack creates a message with the captured panic, timestamp, and hostname,
// and posts it to the configured Slack channel.
func postToSlack(panic interface{}) {
  ...
}

func reportPanics() {
  // Capture the panic if there is one, and report it.
  if panic := recover(); panic != nil {
    postToSlack(panic)
  }
}

// Version without panic reporting; this is not what you want!: 
func runWithoutPanicReporting() {
  // myFunc encapsulates the core logic to do something.
  // Run it in a separate goroutine.
  go myFunc()
}

// Version with panic reporting; this is what you want:
func runMyFuncPanicReporting() {
  go func() {
    // Defer reportPanics before calling myFunc --  
    // if myFunc panics, reportPanic will capture and report the panic right before
    // the goroutine exits.
    defer reportPanics()
    myFunc()
  }()
}

func PanicReporterMiddleware(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
  defer reportPanics()
  next(w, r)
}

// server.go
func runServer() {
  // Set up your routes.
  router := setUpRouter()

  // Chain the PanicReporter middleware first:
  // this example uses the negroni middleware library, but you can set this up
  // in any middleware library.
  n := negroni.New()
  n.Use(negroni.HandlerFunc(PanicReporterMiddleware))
  n.UseHandler(router)

  // Run the HTTP server.
  http.ListenAndServe(":3001", n)
}