# обработка паники

Две встроенные функции, **panic** и **recover**, помогают в составлении отчетов и обработке паники во время выполнения (run-time panics) и программно определенных ошибочных условий.

```
func panic(interface{})
func recover() interface{}
```

При выполнении функции F явный вызов **panic** или паники во время выполнения (run-time panic) завершает выполнение F. Любые функции, отложенные (deferred) с помощью F, затем выполняются как обычно. Затем выполняются все отложенные функции, выполняемые вызывающей стороной F, и так далее, вплоть до любой отложенной функции верхнего уровня в выполняющейся процедуре. В этот момент программа завершается и сообщается об ошибке, включая значение аргумента для паники. Эта последовательность завершения называется **паникой**.

```
panic(42)
panic("unreachable")
panic(Error("cannot parse"))
```

Функция **recover** позволяет программе управлять поведением паникующей программы. Предположим, что функция G откладывает функцию D, которая вызывает recover, и паника возникает в функции той же программы, в которой выполняется G. Когда выполнение отложенных функций достигает D, возвращаемым значением вызова D для recover будет значение, переданное вызову паники. Если D возвращается нормально, без начала новой паники, последовательность паники останавливается. В этом случае состояние функций, вызываемых между G и вызовом паники, отбрасывается, и нормальное выполнение возобновляется. Любые функции, отложенные G перед D, затем запускаются, и выполнение G прекращается, возвращаясь к своему вызывающему.

Возвращаемое значение recover равно nil, если выполняется любое из следующих условий:

* аргумент паники был nil;
* goroutine не паникует;
* recover не была вызвана напрямую отложенной функцией.

Функция protect в приведенном ниже примере вызывает аргумент функции g и защищает вызывающих от паники во время выполнения, вызванной g.

```
func protect(g func()) {
    defer func() {
        // Println выполняется нормально, 
        // даже если есть паника
        log.Println("done")  
        if x := recover(); x != nil {
            log.Printf("run time panic: %v", x)
        }
    }()
    log.Println("start")
    g()
}
```
