recover в Golang
Как работает recover
В Go функция recover
используется для обработки паник (panic). Паника — это механизм, который останавливает нормальное выполнение программы и начинает её аварийное завершение. recover
позволяет «перехватить» панику и восстановить выполнение программы, чтобы она не завершилась аварийно.
Как работает recover
recover
работает только внутри отложенных функций (deferred functions).- Если паника произошла,
recover
возвращает значение, переданное вpanic
. - Если паники не было,
recover
возвращаетnil
.
Синтаксис
1 2 |
func recover() interface{} |
Пример использования recover
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package main import "fmt" func main() { defer func() { if r := recover(); r != nil { fmt.Println("Recovered from panic:", r) } }() fmt.Println("Start") panic("something went wrong") // Вызываем панику fmt.Println("This will not be printed") // Этот код не выполнится } |
1 2 3 |
Start Recovered from panic: something went wrong |
Как это работает
- В функции
main
вызываетсяpanic
, что приводит к аварийной остановке программы. - Перед этим выполняется отложенная функция (deferred function), в которой вызывается
recover
. recover
перехватывает панику и возвращает значение, переданное вpanic
.- Программа продолжает выполнение после паники, а не завершается аварийно.
Использование recover
для безопасного выполнения кода
recover
часто используется для обработки ошибок в критических участках кода, чтобы программа могла продолжить работу даже в случае сбоев.
Пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package main import "fmt" func safeDivide(a, b int) (result int, err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("recovered from panic: %v", r) } }() if b == 0 { panic("division by zero") // Вызываем панику, если делитель равен 0 } return a / b, nil } func main() { result, err := safeDivide(10, 0) if err != nil { fmt.Println("Error:", err) } else { fmt.Println("Result:", result) } } |
Вывод:
1 2 |
Error: recovered from panic: division by zero |
Использование recover
в горутинах
Если паника происходит внутри горутины, она не влияет на другие горутины. Однако, если паника не обработана, программа завершится аварийно. Чтобы этого избежать, используйте recover
внутри горутины.
Пример:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
package main import ( "fmt" "time" ) func worker() { defer func() { if r := recover(); r != nil { fmt.Println("Recovered in worker:", r) } }() fmt.Println("Worker started") panic("something went wrong in worker") fmt.Println("Worker finished") // Этот код не выполнится } func main() { go worker() time.Sleep(1 * time.Second) // Даем время горутине завершиться fmt.Println("Main finished") } |
1 2 3 4 |
Worker started Recovered in worker: something went wrong in worker Main finished |
Когда использовать recover
- Критические участки кода: Например, при работе с внешними ресурсами (базами данных, файлами, сетевыми запросами), где возможны неожиданные ошибки.
- Горутины: Для предотвращения аварийного завершения программы из-за паники в горутинах.
- Тестирование: Для обработки паник в тестах.
Ограничения recover
recover
работает только внутри отложенных функций.- Если
recover
вызывается вне отложенной функции, он не перехватит панику. recover
не может перехватить панику, если она произошла в другой горутине (если толькоrecover
не находится в той же горутине).
Итог
recover
— это мощный инструмент для обработки паник в Go.- Используйте его в отложенных функциях для безопасного выполнения кода.
- Применяйте
recover
в горутинах, чтобы предотвратить аварийное завершение программы. - Не злоупотребляйте
recover
: паники должны использоваться только для действительно критических ошибок, а не для обычного управления потоком выполнения.
Recommended Posts
Golang map и Swiss Table
16.03.2025