Как обработать panic и вернуть 500 http в go?

Пользователь

от jaren , в категории: Golang , 2 года назад

Как обработать panic и вернуть 500 http в go?

Facebook Vk Ok Twitter LinkedIn Telegram Whatsapp

2 ответа

Пользователь

от alisa.bahringer , 2 года назад

@jaren 

В Go, при возникновении паники (panic), можно обработать ее с помощью механизма "recover". Этот механизм позволяет программисту перехватить панику и выполнить дополнительные действия перед завершением программы.


Чтобы вернуть HTTP-код 500 в случае паники, можно использовать конструкцию defer-recover. Код будет выглядеть примерно так:

1
2
3
4
5
6
7
8
func handler(w http.ResponseWriter, r *http.Request) {
    defer func() {
        if err := recover(); err != nil {
            http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
        }
    }()
    // код вашего обработчика здесь
}


Этот код перехватывает любые паники, которые могут возникнуть внутри обработчика, и возвращает HTTP-код 500 вместе с сообщением об ошибке. Вы можете настроить сообщение об ошибке на свое усмотрение.


Также, для удобства, можно создать отдельную функцию для обработки ошибок и использовать ее в своих обработчиках:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
func handleError(w http.ResponseWriter, err error) {
    log.Println(err)
    http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
}

func handler(w http.ResponseWriter, r *http.Request) {
    defer func() {
        if err := recover(); err != nil {
            handleError(w, fmt.Errorf("panic: %v", err))
        }
    }()
    // код вашего обработчика здесь
}


В этом примере мы создаем отдельную функцию handleError, которая логирует ошибку и возвращает HTTP-код 500. Обработчик handler использует эту функцию для обработки ошибок, которые могут возникнуть внутри него.

Пользователь

от amaya_bahringer , год назад

@jaren 

Логика обработки паники может отличаться в зависимости от требований вашего приложения или фреймворка, которым вы пользуетесь. Однако, всякий раз при возникновении паники вы можете вызывать функцию-обработчик и передавать в нее объект ResponseWriter и панику. Далее вы можете использовать методы ResponseWriter для отправки интересующего вас HTTP-кода и сообщения об ошибке.


Ниже приведен пример кода, используя стандартный пакет net/http:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package main

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

func main() {
	http.HandleFunc("/", handler)
	http.ListenAndServe(":8080", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
	defer func() {
		if err := recover(); err != nil {
			log.Println("panic occurred:", err)
			http.Error(w, "Internal Server Error", http.StatusInternalServerError)
		}
	}()

	// код вашего обработчика здесь

	// Пример паники для тестирования
	panic("Something went wrong")
}


В этом примере мы регистрируем обработчик "/" для корневого пути и запускаем сервер на порту 8080. Обработчик имеет структуру, аналогичную предыдущему примеру. Внутри блока defer есть проверка на панику. Если паника возникла, мы логируем ее и отправляем HTTP-код 500 и сообщение "Internal Server Error". Помимо этого, вы можете выполнять другие операции, такие как сохранение стека вызовов и отправка уведомлений о панике на почту или другие каналы связи, в зависимости от требований вашего приложения.


Обратите внимание, что использование recover() в других функциях отличных от handler() не позволит перехватить панику, поэтому рекомендуется использовать этот механизм в самом обработчике или централизованно в middleware, если вы используете фреймворк.