go select 语句中发送和接收操作之间的优先级规则

发布于 2025-01-10 21:30:22 字数 745 浏览 0 评论 0原文

go select 语句中的发送和接收操作之间是否有优先级规则?

由于“发送”操作总是准备就绪,不像“接收”操作等待来自通道的数据,所以我总是感觉“发送”将在选择时首先执行。

我尝试了一些代码来测试当发送和接收都准备好时会发生什么:

package main

import (
    "fmt"
    "time"
)

func main() {
    ch1 := make(chan string)
    ch2 := make(chan string)
    go goOne(ch1)
    go goTwo(ch2)

    time.Sleep(time.Second * 2)
    select {
    case ch2 <- "To goTwo goroutine":
    case msg1 := <-ch1:
        fmt.Println(msg1)
    }
}

func goOne(ch chan string) {
    ch <- "From goOne goroutine"
}

func goTwo(ch chan string) {
    msg := <-ch
    fmt.Println(msg)
}

结果似乎总是“来自 goOne goroutine”。所以看来接收操作具有优先权。 但这是设计的结果吗?或者可能会发生发送者首先被执行的情况吗?我在文档中找不到信息

如果我希望接收操作具有优先级,我可以依靠它还是应该做其他事情?

谢谢!

Is there a priority rule between sent and receive operation in a go select statement ?

Since a "send" operation is always ready, not like a "receive" operation that wait for something to come from the channel, I always have the feeling that the "send" will be executed first on a select.

I tried a little code to test what happens when both send and receive are ready:

package main

import (
    "fmt"
    "time"
)

func main() {
    ch1 := make(chan string)
    ch2 := make(chan string)
    go goOne(ch1)
    go goTwo(ch2)

    time.Sleep(time.Second * 2)
    select {
    case ch2 <- "To goTwo goroutine":
    case msg1 := <-ch1:
        fmt.Println(msg1)
    }
}

func goOne(ch chan string) {
    ch <- "From goOne goroutine"
}

func goTwo(ch chan string) {
    msg := <-ch
    fmt.Println(msg)
}

The result seems to always be "From goOne goroutine". So it seems the receive operation has the priority.
But is it by design effect ? Or could it happen that the sent got executed first? I couldn't find the info in the doc

If I want the receive operation to have the priority, can I rely on that or should I do something else ?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

千鲤 2025-01-17 21:30:22

go select 语句中的发送和接收操作之间是否有优先级规则?

不会。当多个 case 同时准备就绪时,会随机执行一个。

由于“发送”操作始终准备就绪

不正确。当另一端没有接收任何内容时,或者当缓冲通道的缓冲区已满时,发送操作可能会阻塞(即未准备好)。

或者可能是发送的内容先被执行?

是的,但选择这种情况时,您可能看不到任何输出,因为您的程序在 main 中恢复执行,并在 goTwo 协程实际打印任何内容之前立即退出。

如果我希望接收操作具有优先级[...]

select 语句的语义是:“先执行准备好的那个”。如果一种情况必须优先于另一种情况,请将另一种情况更改为默认情况(如果没有其他情况则运行):

    select {
    case msg1 := <-ch1:
        fmt.Println(msg1)
    default:
        ch2 <- "To goTwo goroutine"
    }

Is there a priority rule between sent and receive operation in a go select statement?

No. When more than one case is ready at the same time, one at random is executed.

Since a "send" operation is always ready

Not true. A send operation may just block (i.e. not ready) when nothing is receiving on the other side, or when a buffered channel's buffer is full.

Or could it happen that the sent got executed first?

Yes, but you may see no output when this case is selected because your program resumes execution in main and exits immediately before the goTwo goroutine can actually print anything.

If I want the receive operation to have the priority [...]

The very semantics of a select statement are: "execute whichever is ready first". If one case must have priority over the other, change the other one to default (runs if nothing else is ready):

    select {
    case msg1 := <-ch1:
        fmt.Println(msg1)
    default:
        ch2 <- "To goTwo goroutine"
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文