Как обработать панику и вернуть 500 http GO
Пишу сервер на GO. Столкнулся с необходимостью обработки паник. Если где-то случается паника то сервер ничего не отвечает. Нужно чтобы вернул 500 код.
Намутил пока что такой код (сильно упрощённый и удалённый от реального):
package main
import (
"net/http"
"fmt"
"log"
)
// Функция, которая обрабатывает наш запрос, вызывается из main
func view(res http.ResponseWriter, req *http.Request) {
// запишем статус ответа 200
res.WriteHeader(http.StatusOK)
/* допустим для определения контента нам нужно выполнить
какой-либо код, в нём возникает паника */
var test map[string]string
test["hello"] = "world"
res.Write([]byte("Hello, it's main page!"))
}
func main() {
fmt.Println("Starting serve on :8000")
// ждём запроса по адресу "/"
http.HandleFunc("/", func(res http.ResponseWriter, req *http.Request) {
// запускаем отложенную функцию для отслеживания паник
defer func() {
/* если произошла паника, то вывести ошибку в консоль
и выернуть http 500 */
if err := recover(); err != nil {
log.Println("Panic occurred:", err)
// http пакет ругается здесь, об этом ниже
res.WriteHeader(http.StatusInternalServerError)
}
}()
// функция которая обрабатывает запрос
view(res, req)
})
// Запустить прослушивание сокета
http.ListenAndServe(":8000", nil)
}
Комменты написал, думаю понятно где что. Если что пишите комментарии, добавлю больше объяснений. Суть в том, что при таком раскладе http пакет ругается на то, что я пытаюсь перезаписать уже записанный 200 код и не делает этого. Да самое банальное, это устанавливать код ответа и контент в самом конце функции, после всех действий. Но я через некоторое время могу это забыть, когда буду писать вьюшки или кто-то другой может редактировать мой код. Его поведение в таком случае будет очень неочевидным, поэтому это мне больше напоминает какой-то костыль. Есть способы сделать это лучше?
Ответы (1 шт):
Нужно пользоваться функцией http.Error
Обработка ошибок в вашем примере может выглядеть вот так:
if err := recover(); err != nil {
log.Println("Panic occurred:", err)
// http пакет ругается здесь, об этом ниже
http.Error(res, "Internal error: "+err.Error(), http.StatusInternalServerError)
}