Sobes.tech
Back to questions
Senior
2

func main() { defer func() { if r := recover(); r != nil { fmt.Println("recovered") } }() defer func() { fmt.Println("defer") }() go func() { fmt.Println("inside goroutine start") panic("boom") fmt.Println("inside goroutine end") }() time.Sleep(time.Second) }

Companies where asked
CRTEX

Answer from AI

sobes.tech AI

В данном коде есть несколько важных моментов, связанных с поведением defer, recover и горутин:

  1. В main объявлены два defer:

    • Первый с recover(), который ловит панику и выводит "recovered".
    • Второй просто выводит "defer".
  2. Запускается горутина, которая выводит "inside goroutine start", затем вызывает panic("boom"), после чего код не выполняется.

  3. time.Sleep(time.Second) даёт время горутине выполниться.

Ключевой момент: recover() работает только если паника происходит в той же горутине, где вызван defer с recover. В данном случае паника происходит в отдельной горутине, а recover находится в main.

Что произойдет при запуске:

  • В main отложенные функции будут вызваны при выходе из main.
  • Горутина выведет "inside goroutine start", затем паника "boom" приведёт к аварийному завершению этой горутины, но не всей программы.
  • recover в main не сработает, так как паника не в main.
  • Отложенная функция fmt.Println("defer") в main выполнится.

Вывод в консоль:

inside goroutine start
defer

Паника в горутине не будет поймана, и сообщение "recovered" не выведется.

Если нужно обработать панику в горутине, recover должен быть внутри той же горутины:

go func() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Println("recovered in goroutine")
        }
    }()
    fmt.Println("inside goroutine start")
    panic("boom")
}()

Тогда паника будет поймана, и программа не упадёт.