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

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

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-12-08 11:45:11421ブラウズ

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

Go の select ステートメントでの優先順位制御

Go では、select ステートメントによりゴルーチン間の非同期通信が可能になります。ただし、case ブロックの評価順序によっては、予期しない結果が生じる場合があります。この問題は、コンテキストがキャンセルされたときにルーチンをすぐに終了するなど、特定のケースの処理を優先しようとするときに発生します。

次のコードを考えてみましょう。

func sendRegularHeartbeats(ctx context.Context) {
    for {
        select {
        case <-ctx.Done():
            return
        case <-time.After(1 * time.Second):
            sendHeartbeat()
        }
    }
}

問題:
このコードの目的は、time.After() よりも ctx.Done() ケースの処理を優先することです。 場合。ただし、Go の非決定的な評価順序により、time.After() ケースが最初に評価される場合があり、コンテキストがキャンセルされた場合でもハートビートが送信されることがあります。

解決策:
受け入れられた回答で提案された解決策は、ctx.Done() のノンブロッキングチェックを備えたネストされた select ステートメントを追加することを提案しています。ただし、ハートビートが送信される可能性は依然として高いため、これで問題が完全に解決されたわけではありません。

より効果的なアプローチは、デフォルトのケースを ctx.Done() ケースに追加して、ctx.Done() ケースの処理を優先することです。外側の選択ステートメント:

func sendRegularHeartbeats(ctx context.Context) {
    ticker := time.NewTicker(time.Second)
    defer ticker.Stop()

    for {
        select {
        case <-ctx.Done():
            return
        default:
        }

        select {
        case <-ctx.Done():
            return
        case <-ticker.C:
            sendHeartbeat()
        }
    }
}

これにより、ctx.Done() ケースが外側の選択ステートメントで最初に評価され、優先順位が高くなります。コンテキストがキャンセルされた場合、ルーチンはすぐに戻り、ハートビートは送信されません。 time.After() ケースが最初に到着した場合、外側の select ステートメントのデフォルトのケースにより無視されます。

以上がGo の「select」ステートメントでコンテキストのキャンセルを優先するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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