Go での子 goroutine パニックからの回復
最近のプログラミング作業中に、呼び出し側関数の能力という基本的な前提に疑問が生じました。子ゴルーチンのパニックから回復します。一般通念ではそうではないと示唆されていましたが、子ゴルーチンがパニックに陥った場合、呼び出し元の遅延回復メカニズムではプログラム全体の終了を防ぐことができないことが判明しました。
この不可解な動作を説明するために、次のコードを考えてみましょう。
<code class="go">func fun1() { fmt.Println("fun1 started") defer func() { if err := recover(); err != nil { fmt.Println("recover in func1") } }() go fun2() time.Sleep(10 * time.Second) // wait for the boom! fmt.Println("fun1 ended") } func fun2() { fmt.Println("fun2 started") time.Sleep(5 * time.Second) panic("fun2 booom!") fmt.Println("fun2 ended") }</code>
興味深いことに、fun1 が fun2 のパニックの前に終了するか後に終了するかに関係なく、fun1 の遅延回復メカニズムが効果がないことが判明し、プログラムが即座に終了します。
失敗
Go 仕様では、この型破りな動作について明確に説明されています。
関数 F の実行中に、パニックまたは実行時パニックへの明示的な呼び出しにより、F の実行が終了します。 F によって遅延された関数は通常どおり実行されます。 次に、F の呼び出し元によって実行される遅延関数が実行され、実行中のゴルーチンのトップレベル関数によって遅延される関数まで実行されます。 その時点で、プログラムは終了します。
この場合、fun2 はそれぞれの goroutine で実行される最上位関数を表します。 fun2 には回復メカニズムがないため、プログラムは、fun1 またはその先行プログラムで遅延された回復の試行を無視して、パニック時に終了します。
この動作は、重要な違いを強調しています。ゴルーチンは、次のような原因で発生したパニックから回復することはできません。別のゴルーチン。その結果、fun1 の遅延リカバリは無駄になります。fun2 のパニックによりゴルーチンとその後のリカバリ作業が効果的に終了するためです。
以上が呼び出し元関数は Go の子ゴルーチンのパニックから回復できますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。