D
D
Dmitry Shnyrev2014-11-06 10:28:31
go
Dmitry Shnyrev, 2014-11-06 10:28:31

How do you handle errors in a Go web application?

Hey!
Share a recipe on how to correctly collect and handle errors in a Go web application.
For myself, I have found such an option so far, I'm not sure if this is a good example: I use the https://github.com/golang/glog
library, I just put if err != nil { glog.Fatalln(err) } anywhere in the application and in the browser I get 500 Server internal error, and in the logs: F1106 07:15:27.296630 02050 services.go:42] My Error where you can see when and where the error occurred. (! I chose a bad way - upd below) I also found information here https://sourcegraph.com/blog/google-io-2014-buildi...


Handler functions: We define our handlers with an error return value, and we use a simple wrapper function to make them implement http.Handler. This means we can centralize error handling instead of having to format error messages and pass them to the http.Error for each possible error. Our handler functions look like:
func serveXYZ(w http.ResponseWriter, r *http.Request) error { ... }

Tried. But collecting an error and raising it up the hierarchy to the highest level is somehow not very beautiful in the end.
What recipes do you have? What can you say about this?
upd: I develop using gin, which is responsible for restarting the server. Therefore, it turned out that after glog.Fatal the server was cut down by os.Exit(255), and gin turned it back on. It seemed to me that the current request is simply completed. I tried to start the server directly and indeed the server stopped on the line with an error. Not good :(.
pps: I opened a project for myself with several files in one package, you can’t just start it with go run server.go, you have to do go run *.go! Oh how :). Up to this point, gin has been loading files from one package :)

Answer the question

In order to leave comments, you need to log in

2 answer(s)
S
SilentFl, 2014-11-06
@dmnBrest

if you do everything manually via net/http, then you can catch panic (well, or error), and log with the necessary info:

package main

import (
  "fmt"
  "log"
  "net/http"
)

func handle(w http.ResponseWriter, r *http.Request) {
  defer func() {
    if s := recover(); s != nil {
      log.Printf("Recover in %s\n", s)
      log.Printf("Request: %s\n", fmt.Sprintf("%+v", r))
      http.Error(w, "Sorry, something wrong. Try later", 500)
    }
  }()

  // тут делаем какую-то вещь, которая крашит горутину (допустим, валится вызов библиотечной функции)
  // для примера сделаем так:
  someCondition := true
  if someCondition {
    panic("Root")
  }

  w.Write([]byte("Hello"))
}

func main() {
  http.Handle("/", http.HandlerFunc(handle))
  http.ListenAndServe(":8080", nil)
}

well, if you use any framework, then look at its documentation; let's say beego has its own logger, with levels and everything else

D
Dmitry Shnyrev, 2014-11-06
@dmnBrest

Found such an interesting service
https://deferpanic.com/

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question