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) }
Answer from AI
sobes.tech AI
В данном коде есть несколько важных моментов, связанных с поведением defer, recover и горутин:
-
В
mainобъявлены дваdefer:- Первый с
recover(), который ловит панику и выводит "recovered". - Второй просто выводит "defer".
- Первый с
-
Запускается горутина, которая выводит "inside goroutine start", затем вызывает
panic("boom"), после чего код не выполняется. -
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")
}()
Тогда паника будет поймана, и программа не упадёт.