Golang のチャネル出力順序を理解する
Golang では、バッファリングされていないチャネルがゴルーチン間の信頼性の高い通信メカニズムを提供します。ただし、出力順序が混乱を招く場合があります。次のコードを考えてみましょう:
func main() { messages := make(chan string) go func() { messages <- "hello" }() go func() { messages <- "ping" }() msg := <-messages msg2 := <-messages fmt.Println(msg) fmt.Println(msg2) }
このコードを実行すると、一貫して「ping」の後に「hello」が出力されます。出力がゴルーチンの作成順序と一致すると予想されるため、これは直観に反するように思えるかもしれません。
これが発生する理由を理解するには、チャネルが通信パイプラインであり、ゴルーチンが並列タスクを表すことを覚えておくことが重要です。ゴルーチンが特定の順序で作成された場合でも、ゴルーチンの実行順序は保証されません。
この場合、スケジューラは、「hello」を送信するゴルーチンよりも前に「ping」を送信するゴルーチンをスケジュールした可能性があります。最初の受信者 (つまり、msg := <-messages) が利用可能になると、すでにスケジュールされた「ping」ゴルーチンからのメッセージを受け入れます。
最初のメッセージを受信すると、プログラムは実行を継続します。 2 番目の受信者 (msg2 := <-messages) が利用可能になるまで。この時点で、「hello」メッセージを送信する準備ができており、2 番目のメッセージとして受け入れられます。
したがって、出力順序は、チャネルに書き込むゴルーチンの実行順序によって決まります。メッセージが作成される順序や、メッセージがチャネルから読み取られる順序ではありません。これを確認するには、提供された回答で提案されているように、ゴルーチンに Println ステートメントを追加できます:
... func() { messages <- "hello"; fmt.Println("Hello sent") }() func() { messages <- "ping"; fmt.Println("Ping sent") }() ...
これは出力します:
Hello sent Ping sent ping hello
これにより、メッセージが送信されたことが確認されます。同じ順序で印刷されます。
以上がGolang のバッファリングされていないチャネル出力順序が直観に反するように見えるのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。