Проверяет понимание механизма обработки паник в Go и обязательного использования defer для вызова recover.
В Go паника (panic) — это механизм аварийного завершения работы функции или горутины. Когда происходит паника, выполнение текущей функции немедленно прекращается, и начинается разворачивание стека вызовов. В процессе разворачивания выполняются все отложенные (defer) функции, которые были зарегистрированы в текущей горутине. Функция recover позволяет перехватить панику и восстановить нормальное выполнение, но только если она вызвана внутри отложенной функции.
Когда паника происходит, Go начинает разворачивать стек: он завершает текущую функцию, затем её вызывающую и так далее, пока не дойдёт до main или не будет вызван recover. На каждом уровне выполняются defer-функции. Если recover вызывается вне defer, он возвращает nil, потому что паника уже не может быть перехвачена — код выполняется в нормальном потоке, а не в процессе разворачивания стека.
package main
import "fmt"
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
fmt.Println("Before panic")
panic("something went wrong")
fmt.Println("After panic") // не выполнится
}В этом примере recover вызывается внутри defer, поэтому он успешно перехватывает панику и выводит сообщение. Если бы recover был вызван вне defer, он бы не сработал.
Recover используется для graceful shutdown серверов, обработки критических ошибок в долгоживущих горутинах, логирования паник без завершения программы. Например, в веб-серверах на Go часто используют middleware с recover, чтобы не ронять весь сервер из-за одной паники в обработчике запроса.
Recover должен вызываться через defer, потому что только отложенные функции выполняются в контексте разворачивания стека после паники. Это позволяет безопасно перехватывать ошибки и продолжать работу программы, не допуская её аварийного завершения.