Golang频道输出顺序

hun*_*tea 1 channel 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)
Run Code Online (Sandbox Code Playgroud)

上面的代码在我的终端上始终打印"ping"然后"hello".我对这个打印的顺序很困惑,所以我想知道我是否可以对我的想法做一些澄清.

据我所知,在等待发送方和接收方时,无缓冲的通道都在阻塞.因此,在上述情况下,当执行这两个例程时,在两种情况下都没有接收器.所以我猜这两个例程都会阻塞,直到通道上的接收器可用.

现在......我会假设第一个"你好"被尝试进入频道,但必须等待......同时,"ping"尝试,但再次必须等待.然后

msg := <- messages
Run Code Online (Sandbox Code Playgroud)

显示,所以我假设在那个阶段,程序将任意选择一个等待的goroutine并允许它将其消息发送到通道,因为msg已准备好接收.

然而,似乎无论我运行多少次程序,总是msg被分配"ping"而msg2被分配为"hello",这给人的印象是"ping"始终优先发送到第一个(到MSG).这是为什么?

Him*_*shu 6

在 Golang Spec Channels order中描述为:-

通道充当先进先出队列。例如,如果一个 goroutine 在通道上发送值,而第二个 goroutine 接收它们,则按照发送的顺序接收值。

它将打印哪个值首先可用以在另一端接收。如果要同步它们,请使用不同的频道或添加wait Groups.

package main

import (
    "fmt"
)

func main() {
  messages1 := make(chan string)
  messages2 := make(chan string)
  go func(<-chan string) {
        messages2 <- "ping" 
    }(messages2)
  go func(<-chan string) {
        messages1 <- "hello" 
    }(messages1)
  fmt.Println(<-messages1)
  fmt.Println(<-messages2)
}
Run Code Online (Sandbox Code Playgroud)

如果您看到,您可以根据您的选择使用不同的渠道轻松获得您想要的任何价值。

去游乐场


Ale*_*nok 5

这不是关于读取频道的顺序,而是关于goroutines执行的顺序,这是无法保证的.

尝试从你写入频道的函数(写入之前和之后)'打印',我认为它应该与从频道读取的顺序相同.