コンテキストのキャンセルの失敗: 結果と解決策
Go の同時実行環境では、コンテキストがゴルーチンの有効期間と動作を制御します。これは、期限、キャンセル信号、その他の重要な情報を伝達する手段を提供します。ただし、コンテキストを適切にキャンセルしないと、望ましくない結果が生じる可能性があります。
次のコード スニペットを考えてみましょう。
func Call(ctx context.Context, payload Payload) (Response, error) { req, err := http.NewRequest(...) // Some code that creates request from payload ctx, cancel = context.WithTimeout(ctx, time.Duration(3) * time.Second) defer cancel() return http.DefaultClient.Do(req) }
ここでは、新しいコンテキストが 3 秒のタイムアウトで作成されます。 defer cancel() ステートメントを使用しない場合、関数はコンテキストを明示的にキャンセルせずに戻ります。これにより go vet からの警告がトリガーされます:
context によって返されたキャンセル関数。コンテキスト リークを避けるために、破棄せずに WithTimeout を呼び出す必要があります
では、Contextがキャンセルされなかった場合はどうなるのでしょうか?この省略により、システムに「漏れ」が生じます。コンテキストのキャンセルの処理を担当するゴルーチンは、何の目的も持たないにもかかわらず、無期限にアクティブなままになります。この無駄なリソースがプログラム内で頻繁に発生すると、重大なメモリ オーバーヘッドが発生する可能性があります。
コンテキスト リークを回避するには、キャンセルをすぐに延期することがベスト プラクティスと考えられます( ) WithCancel() または WithTimeout() を使用して新しいコンテキストを作成した後。これにより、初期の戻りや例外に関係なく、関数が戻るとすぐにキャンセル ロジックが実行されるようになります。
要約すると、コンテキストのキャンセルを怠ると、ゴルーチンが無限に実行されたままになり、メモリ リークが発生する可能性があります。これを防ぐには、常に WithCancel() または WithTimeout() を使用して新しい Context を作成した直後にキャンセル関数を延期してください。
以上がGo でコンテキストのキャンセルを常に延期する必要があるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。