Go ではチャネルからメッセージが受信される順序を理解するのは少し難しい場合があります。あなたが提供したコードを詳しく見てみましょう:
func main() { messages := make(chan string) go func() { messages <- "hello" }() go func() { messages <- "ping" }() msg := <-messages msg2 := <-messages fmt.Println(msg) fmt.Println(msg2) }
次の説明はあなたの懸念に対処し、何が起こっているのかをより明確に理解します:
まず、次のようなブロック操作を理解することが重要です。バッファリングされていないチャネルからの送受信は、順序を保証するものではありません。 Go では、ゴルーチンの実行は同時実行され、デフォルトではゴルーチンの実行順序は定義されていません。
最初のゴルーチンがチャネルに「hello」を送信しようとしたとき、現在待機している受信者がいない場合、ゴルーチンはブロックされました。同様に、2 番目のゴルーチンが「ping」を送信しようとすると、これもブロックされます。
ここで、msg := <-messages ステートメントに到達すると、プログラムはブロックされているゴルーチンの 1 つを任意にブロック解除します。ブロックされていないゴルーチンによって送信されたメッセージは、msg で受信されます。
同じプロセスが msg2 := <-messages でも発生します。別のゴルーチンのブロックが解除され、そのゴルーチンによって送信されたメッセージが msg2 で受信されます。
ゴルーチンのブロックが解除されてメッセージがメッセージに送信される順序は決定的ではありません。これが、ルーチンが代わりに実行されるはずであると仮定していたにもかかわらず、一貫して「hello」の前に「ping」が出力される理由です。
これを確認するには、ゴルーチンに print ステートメントを追加してみてください。
func main() { messages := make(chan string) go func() { fmt.Println("Sending 'hello'") messages <- "hello" fmt.Println("Sent 'hello'") }() go func() { fmt.Println("Sending 'ping'") messages <- "ping" fmt.Println("Sent 'ping'") }() msg := <-messages msg2 := <-messages fmt.Println(msg) fmt.Println(msg2) }
コードを数回実行すると、ゴルーチンからの print ステートメントの順序が異なる場合があることがわかります。これは、ゴルーチン実行の非決定的な性質をさらに示しています。
要約すると、バッファリングされていないチャネルでは、チャネルからの出力の順序は保証されず、対応するゴルーチンのブロックが解除される順序に依存します。
以上がGo のバッファリングされていないチャネルの出力順序が非決定的なのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。