Go ルーチンでのパニックの処理
Go ルーチンは Go プログラムで同時実行性を提供しますが、これらのルーチン内でパニックが発生すると課題が生じる可能性があります。パニックから回復するには、通常、recover() 関数が使用されます。ただし、ゴルーチン内で、recover() が期待どおりに動作しない場合があります。
Go ルーチンでのリカバリの失敗を理解する
次のコード ブロックを考えてみましょう。
func main() { done := make(chan int64) defer fmt.Println("Graceful End of program") defer func() { r := recover() if _, ok := r.(error); ok { fmt.Println("Recovered") } }() go handle(done) for { select{ case <- done: return } } } func handle(done chan int64) { var a *int64 a = nil fmt.Println(*a) done <- *a }
このコードは、main 関数の遅延関数を使用して、ゴルーチンのパニックから回復しようとします。しかし、パニック状態を回復することはできません。逆に、次のコード ブロックは期待どおりに動作します。
func main() { done := make(chan int64) defer fmt.Println("Graceful End of program") defer func() { r := recover() if _, ok := r.(error); ok { fmt.Println("Recovered") } }() handle(done) for { select{ case <- done: return } } } func handle(done chan int64) { var a *int64 a = nil fmt.Println(*a) done <- *a }
リカバリの問題の解決
この動作を理解する鍵は、ゴルーチンの性質にあります。 reverse() は、それが呼び出された同じ goroutine 内で発生したパニックからのみ回復できます。 Go ブログより:
現在のゴルーチン内のすべての関数が戻るまでプロセスはスタックを上っていき、その時点でプログラムはクラッシュします
ゴルーチンでパニックを処理するには、
func handle(done chan int64) { defer func() { if r := recover(); r != nil { if _, ok := r.(error); ok { fmt.Println("Recovered in goroutine") } } }() var a *int64 a = nil fmt.Println(*a) done <- *a }
ゴルーチン内に回復関数を配置することで、パニックを遮断し、適切に処理できます。
以上がGo ルーチンで「recover()」がパニックを処理できないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。