dmnBrest
@dmnBrest
Salesforce for money. Python, Go, Ruby for soul.

Как вы обрабатываете ошибки в Web приложении на Go?

Привет!

Поделитесь рецептом, как правильно собирать и обрабатывать ошибки в web приложении на Go.
Для себя пока нашел такой вариант, не уверен что это хороший пример:
использую библиотеку https://github.com/golang/glog
просто в любом месте приложения ставлю

if err != nil {
glog.Fatalln(err)
}

и в браузере получаю 500 Server internal error, а в логах:
F1106 07:15:27.296630 02050 services.go:42] My Error
где видно когда и где произошла ошибка.
(! плохой способ я выбрал - upd внизу)

Еще нашел информацию вот здесь 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 { ... }

Попробовал. Но собирать ошибку и поднимать ее по иерархии до самого верхнего уровня как-то не очень красивы в итоге получается.

Какие есть рецепты у вас? Что можете сказать по этому поводу?

upd: Разработку я веду при помощи gin, который отвечает за перезагрузку сервера. Поэтому получилось что после glog.Fatal сервер вырубался по os.Exit(255), а gin врубал его обратно. Мне казалось что просто завершается текущий запрос. Попробовал запустить сервер напрямую и действительно на строчке с ошибкой сервер остановился. Не гуд :(.
pps: сделал для себя открытие проект с несколькими файлами в одном package нельзя просто так оказывается запустить с помощью go run server.go, надо делать go run *.go ! О как :). До этого момента подгрузкой файлов из одного package занимался gin :)
  • Вопрос задан
  • 2499 просмотров
Решения вопроса 2
@SilentFl
если вы делаете все руками через net/http, то можно ловить panic (ну или error), и логировать с нужной инфой:
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)
}


ну а если будете использовать какой-нибудь фреймворк, то смотрите в его документацию; допустим в beego есть свой логгер, с уровнями и всем прочим
Ответ написан
uvelichitel
@uvelichitel Куратор тега Go
habrahabr.ru/users/uvelichitel
"Error values in Go aren’t special, they are just values like any other, and so you have the entire language at your disposal." Rob Pike at Gophercon 2014
Error в Go - это еще не повод для panic. Вы можете сделать запрос к DB и получить error потому, что DB перегружена или сбой на линии или запрос некорректен - это вовсе не основание вызывать glog.Fatalln(err), который сам вызывает os.Exit(255). Просто обрабатывайте error, как значение обычного типа на месте или передавайте выше по стеку вызывов и двигайтесь дальше. Всякий error имеет метод error.Error() возвращающий string для удобства пользования, каковой string можно например отрендерить в HTML пользователю или напечатать в терминал ну или передать в логгер для отладки. Чего уж так сразу panic, fatal?)))
Если я правильно понял вопрос.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
dmnBrest
@dmnBrest Автор вопроса
Salesforce for money. Python, Go, Ruby for soul.
Нашел такой интересный сервис
https://deferpanic.com/
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы