ホームページ >バックエンド開発 >Golang >Go の「select」ステートメントでコンテキストのキャンセルを優先するにはどうすればよいですか?

Go の「select」ステートメントでコンテキストのキャンセルを優先するにはどうすればよいですか?

Patricia Arquette
Patricia Arquetteオリジナル
2024-12-10 09:59:16122ブラウズ

How Can I Prioritize Context Cancellation in Go's `select` Statements?

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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。