Следите за новинками
в нашем Telegram канале. Жми, чтобы подписаться:)
⊗goSpPnRc 54 of 280 menu
◀ ▶

Перехват останова в Go

Останов можно перехватить и продолжить программу со следующей строки вызывающего кода. Для этого в отложенной функции вызывают recover: пока идет размотка стека, она возвращает значение, которое передали при останове, и снимает панику.

После успешного перехвата выполнение не возвращается в хвост функции, где сработал останов. Управление появляется сразу после вызова этой функции у того, кто ее вызвал.

Соберем перехват в main и посмотрим на порядок строк:

package main import "fmt" func work() { fmt.Println("inside") panic("fail") fmt.Println("tail") } func main() { defer func() { if msg := recover(); msg != nil { fmt.Println("caught") } }() work() fmt.Println("main line") }

На экране по очереди "inside", "caught" и "main line". Строка "tail" не печатается: после останова тело work уже не продолжается. Зато "main line" выполняется, потому что перехват вернул управление в main сразу после вызова work.

Тот же прием можно обернуть в отдельную функцию, чтобы не дублировать отложенный блок:

package main import "fmt" func safeRun(fn func()) { defer func() { if msg := recover(); msg != nil { fmt.Println("ok") } }() fn() } func main() { safeRun(func() { panic("x") }) fmt.Println("next") }

Дана функция:

func step() { fmt.Println("step") panic("err") fmt.Println("lost") }

В main перехватите останов из step в отложенной функции и выведите "after" сразу после вызова step.

Дан следующий код:

package main import "fmt" func boom() { panic("no") } func main() { defer func() { recover() }() boom() fmt.Println("live") }

Скажите, появится ли на экране "live".

Скажите, из какой функции выполнение продолжается после перехвата останова внутри work из первого примера урока.

← →
↑
Мы используем cookie для работы сайта, аналитики и персонализации. Обработка данных происходит согласно Политике конфиденциальности.
принять все настроить отклонить