选择缓冲通道与非缓冲通道

Ref*_*ion 3 go

当我运行以下简单代码时,它会按预期打印“ping”:

    messages := make(chan string)

    go func() { messages <- "ping" }()
    fmt.Println(<-messages)
Run Code Online (Sandbox Code Playgroud)

但是,当我在 select 中使用相同的非缓冲通道时,它不会通过 ping 来实现它,从而打印“未发送消息”:

    messages := make(chan string)

    select {
    case messages <- "ping":
        fmt.Println("sent message")
    default:
        fmt.Println("no message sent")
    }
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况?通道是相同的,但可以通过 goroutine 访问,但不能通过 select 访问。

此外,我发现当我将其转换为缓冲通道(大小为 1)时,它会像魅力一样满足通道的要求:为什么?

    messages := make(chan string,1)

    select {
    case messages <- "ping":
        fmt.Println("sent message")
    default:
        fmt.Println("no message sent")
    }
Run Code Online (Sandbox Code Playgroud)

请注意,没有任何挂起,但正如我所描述的那样,立即返回。

bla*_*een 5

select语句将阻塞,直到其中任何一个case准备好为止,或者default如果没有一个准备好,则运行该案例。

\n

在你的第二个程序中,之前没有出现接收操作select,因此case messages <- "ping"未准备好\xe2\x80\x94,没有接收器\xe2\x80\x94,并且default始终执行。

\n

使用缓冲通道,即使另一端没有接收器,发送操作也不会阻塞,因此case messages <- "ping"已准备好并运行。

\n

在带有 goroutine 的代码片段中,发送操作并发运行,因此主程序流程可以继续进行调用fmt.Println并阻塞<-messages,直到并发发送在通道上提供可用的值

\n\n