ホームページ >バックエンド開発 >Golang >Go で入れ子になった「defer」がパニックを回復できないのはなぜですか?

Go で入れ子になった「defer」がパニックを回復できないのはなぜですか?

Linda Hamilton
Linda Hamiltonオリジナル
2024-11-23 10:33:12503ブラウズ

Why Does Nested `defer` Fail to Recover Panics in Go?

ネストされた遅延関数で非効果的なリカバリの背後にある理由を明らかにする

Golang では、recover() は例外を処理し、例外を防ぐための重要なメカニズムとして機能します。パニックの蔓延。ただし、ネストされた遅延関数内でrecover()を使用すると、興味深い観察が生じます。予想に反して、ネストされた遅延が存在するにもかかわらず、パニックが発生する可能性があります。

この異常を説明するために、次のコードを考えてみましょう:

package main

import "fmt"

func printRecover() {
    r := recover()
    fmt.Println("Recovered:", r)
}

func main() {
    // Direct deferred call to recover()
    defer printRecover()

    panic("OMG!")
}

このコードは、実行されると意図したとおりに動作します。

Recovered: OMG!

ただし、ネストされた deferred 内で printRecover() を囲むと、 function:

package main

import "fmt"

func printRecover() {
    r := recover()
    fmt.Println("Recovered:", r)
}

func main() {
    // Nested deferred call to recover()
    defer func() {
        printRecover()
    }()

    panic("OMG!")
}

結果の変更:

Recovered: <nil>
panic: OMG!

goroutine 1 [running]:
main.main()
    /tmp/sandbox898315096/main.go:15 +0x60

この不一致は、recover() の固有の動作に起因します。 Go の仕様に従って、recover():

  • 次の場合は nil を返します:

    • パニック引数が nil でした
    • ゴルーチンは nil ではありませんパニック
    • recover() は遅延オブジェクトによって直接呼び出されませんでしたfunction

ネストされた遅延関数の場合、recover() は最も外側の遅延関数によって直接呼び出されるのではなく、ネストされた遅延関数によって呼び出されます。その結果、nil が返され、パニックが処理されないままになります。

この重要な違いは、Golang で効果的なパニック回復を確実にするために、遅延関数内で直接、recover() を使用することの重要性を強調しています。

以上がGo で入れ子になった「defer」がパニックを回復できないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。