Go プログラムでの一般的なパニックの回復
Go ルーチンを使用する場合、クラッシュやパニックをキャッチして処理したい場合があるかもしれません。これらは内部で発生し、Sentry や Raygun などのエラー報告サーバーに報告される可能性があります。ただし、ゴルーチンは別のゴルーチンのパニックから回復できないことに注意することが重要です。
慣用的なアプローチ
これを処理する慣用的な方法は、コードをgoroutine として起動される関数。これには、パニック状態から回復する機能を提供する、recover() を呼び出す遅延関数の利用が含まれます。
次の例を考えてみましょう。
go func() { defer func() { if r := recover(); r != nil { fmt.Println("Caught:", r) } }() panic("catch me") }()
このコードは、関連するパニックを出力します。
起動するすべてのゴルーチンにこのアプローチを実装するのは現実的ではありませんが、次のようにプロセスを簡素化できます。リカバリ機能を含む名前付き関数を定義し、ゴルーチン内でその関数を呼び出します (遅延呼び出しを使用)。
func logger() { if r := recover(); r != nil { fmt.Println("Caught:", r) } }
遅延クロージャ内でこの関数を呼び出すことで、パニック状況を簡潔に処理できます。
go func() { defer logger() panic("catch me") }()
ラッパーFunction
利便性を高めるために、実際の関数を入力として受け取り、パニック回復プロセスを管理するラッパー関数を作成できます。このラッパー関数は次のように利用できます:
func wrap(f func()) { defer func() { if r := recover(); r != nil { fmt.Println("Caught:", r) } }() f() }
このラッパーを使用すると、パニック処理プロセスがさらに簡素化されます:
go wrap(func() { panic("catch me") })
追加の考慮事項
提供されているサンプル コードは、wrap() 関数内で goroutine が起動される状況を示しています。これにより、呼び出し元は、wrap() 呼び出しの前に go キーワードを指定することで、新しい goroutine が必要かどうかを判断できます。ただし、新しい goroutine で同時に実行したくない場合でも、wrap() 関数を使用して、入力として渡される任意の関数の実行を保護することもできます。
以上がGo ゴルーチンのパニックから回復するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。