Go Select ステートメントの優先順位の指定
特定のシナリオでは、select ステートメント内の case ブロックの実行に優先順位を付けることが重要になります。特に、キャンセル イベントを表すコンテキストを操作する場合、プログラムを適切に終了させるために、Done シグナルが即座に処理されることが不可欠です。
次のコードを考えてみましょう。
func sendRegularHeartbeats(ctx context.Context) { for { select { case <-ctx.Done(): return case <-time.After(1 * time.Second): sendHeartbeat() } } }
このルーチンは実行されます。別のゴルーチンでハートビートを定期的に送信します。ただし、コンテキストがキャンセルされた場合、コードは Done ケースが処理される前にハートビートを送信する場合があります。
select ステートメントのデフォルトの動作では、ケースの評価順序が保証されないため、強制する必要があります。希望する優先順位を明示的に指定します。不完全なアプローチの 1 つは、ハートビート送信を実行する前に閉じたコンテキストをチェックすることです。
func sendRegularHeartbeats(ctx context.Context) { ticker := time.NewTicker(time.Second) defer ticker.Stop() for { // First select select { case <-ctx.Done(): return default: } // Second select select { case <-ctx.Done(): return case <-ticker.C: // Check if context is done again in case a concurrent Done event arrived select { case <-ctx.Done(): default: } sendHeartbeat() } } }
この方法では Done 信号が優先されますが、追加の競合状態が発生します。 Done イベントとティッカー イベントが同時に発生した場合、Done イベントが処理される前にハートビート送信が発生する可能性があります。
残念ながら、現時点では Go にはこの問題に対する完璧な解決策はありません。ただし、提供されている回避策では、ネストされた select ステートメントを導入して元のコードを改善し、そのような競合状態の可能性を最小限に抑えます。
以上がGo の「select」ステートメントでコンテキストのキャンセルを優先するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。