суббота, 22 июня 2019 г.

Спецификация Go: обработка паники

Две встроенные функции, 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()
}


Читайте также:


Комментариев нет:

Отправить комментарий