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

Go の「select」ステートメントでチャネルに優先順位を付けるにはどうすればよいですか?

Patricia Arquette
Patricia Arquetteオリジナル
2024-12-03 03:18:13378ブラウズ

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

Go Select ステートメントの優先順位

Go の select ステートメントを使用して複数のチャネルを操作する場合、チャネルが処理される順序は保証されません。あるチャネルを別のチャネルよりも優先するには、回避策を利用できます。

問題ステートメント

以下のコード スニペットの目標は、出力チャネルのすべての値が確実に一致するようにすることです。出口チャネルの前に処理されます:

package main

import "fmt"

func sender(out chan int, exit chan bool){
    for i := 1; i <= 10; i++ {
        out <- i
    }
    exit <- true
}

func main(){
    out := make(chan int, 10)
    exit := make(chan bool)

    go sender(out, exit)

    L:
    for {
        select {
            case i := <-out:
                fmt.Printf("Value: %d\n", i)
            case <-exit:
                fmt.Println("Exiting")
                break L
        }
    }
    fmt.Println("Did we get all 10? Most likely not")
}

ただし、select ステートメントを使用しても、1 つのチャネルが他のチャネルよりも優先されるわけではありません。 other.

解決策: ネイティブ言語サポート

Go は、「quit」チャネルの可視性をプロデューサーのみに制限することで、select ステートメントでのチャネルの優先順位付けをネイティブにサポートします。プロデューサーが辞めると決めたら、チャンネルを閉じます。コンシューマは、チャネルが空で閉じられている場合にのみ終了します。

package main

import (
    "fmt"
    "math/rand"
    "time"
)

var (
    produced  = 0
    processed = 0
)

func produceEndlessly(out chan int, quit chan bool) {
    defer close(out)
    for {
        select {
        case <-quit:
            fmt.Println("RECV QUIT")
            return
        default:
            out <- rand.Int()
            time.Sleep(time.Duration(rand.Int63n(5e6)))
            produced++
        }
    }
}

func quitRandomly(quit chan bool) {
    d := time.Duration(rand.Int63n(5e9))
    fmt.Println("SLEEP", d)
    time.Sleep(d)
    fmt.Println("SEND QUIT")
    quit <- true
}

func main() {
    vals, quit := make(chan int, 10), make(chan bool)
    go produceEndlessly(vals, quit)
    go quitRandomly(quit)
    for x := range vals {
        fmt.Println(x)
        processed++
        time.Sleep(time.Duration(rand.Int63n(5e8)))
    }
    fmt.Println("Produced:", produced)
    fmt.Println("Processed:", processed)
}

この例では、終了チャネルはプロデューサー関数 (ProduceEndless) にのみ表示されます。プロデューサーは、一定の遅延の後にランダムに終了を決定します。コンシューマ関数 (main) は、vals チャネルが閉じられて空になるまで、vals チャネルを反復処理します。プロデューサーの「終了」メッセージを優先することにより、プログラムが終了する前に vals チャネル内のすべての値が処理されます。

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

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