Как работает механизм `recover` в Go и в каких случаях его стоит использовать?

Ответ

В Go паника (panic) — это механизм для обработки исключительных, непредвиденных ошибок, которые делают дальнейшее выполнение программы невозможным. Для восстановления после паники используется встроенная функция recover().

Ключевое правило: recover() работает только внутри отложенной функции (defer).

Когда в функции происходит panic, её выполнение немедленно прекращается, и начинают выполняться отложенные defer функции. Если одна из этих defer функций вызовет recover(), она перехватит значение, переданное в panic, и выполнение программы возобновится в штатном режиме. Паника прекратится.

package main

import "fmt"

func main() {
    fmt.Println("Начало выполнения main")
    safeFunction()
    fmt.Println("main успешно завершена") // Эта строка выполнится
}

func safeFunction() {
    // Эта отложенная анонимная функция будет вызвана при панике
    defer func() {
        // recover() перехватывает панику
        if r := recover(); r != nil {
            fmt.Printf("Восстановлено после паники: %vn", r)
        }
    }()

    fmt.Println("Вызов опасной функции...")
    causePanic()
    fmt.Println("safeFunction завершена") // Эта строка НЕ выполнится
}

func causePanic() {
    panic("что-то пошло не так")
}

Когда использовать recover:

  1. Предотвращение падения сервера: В веб-серверах или долгоживущих сервисах recover используется в middleware или обработчиках верхнего уровня, чтобы паника в обработке одного запроса не привела к падению всего приложения.
  2. Работа со сторонними библиотеками: Если вы вызываете код, который не контролируете и который может паниковать, можно обернуть вызов в защитную функцию с recover.

Важно: Не используйте panic/recover для обычной обработки ошибок. Для этого в Go предназначен механизм возврата error. Паника — это для исключительных ситуаций, а не для контроля потока выполнения.