Defer, panic, recover: механизм обработки ошибок

К вопросам
Средний
Error Handling

Вопрос

Объясните работу defer, panic и recover. Как они взаимодействуют? В каких случаях следует использовать panic/recover?

Ответ

defer: - Выполняется в обратном порядке (LIFO) при выходе из функции - Выполняется даже при panic - Аргументы вычисляются сразу, но вызов откладывается panic: - Останавливает нормальное выполнение - Раскручивает стек, выполняя defer'ы - Должен использоваться только для критических ошибок recover: - Может перехватить panic только внутри defer - Возвращает значение, переданное в panic

func riskyFunction() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Printf("Перехвачен panic: %v
", r)
        }
    }()
    
    defer fmt.Println("Этот defer выполнится")
    
    panic("Что-то пошло не так!")
    fmt.Println("Эта строка не выполнится")
}

func main() {
    riskyFunction()
    fmt.Println("Программа продолжает работу")
}
func riskyFunction() {
    defer func() {
        if r := recover(); r != nil {
            fmt.Printf("Перехвачен panic: %v
", r)
        }
    }()
    
    defer fmt.Println("Этот defer выполнится")
    
    panic("Что-то пошло не так!")
    fmt.Println("Эта строка не выполнится")
}

func main() {
    riskyFunction()
    fmt.Println("Программа продолжает работу")
}

Дополнительные вопросы

Что происходит с defer при выходе из горутины? Как panic в одной горутине влияет на другие?