为什么golang中的select只适用于goroutine中的channel?

use*_*466 0 channel go

考虑以下去游乐场

    package main

    import "fmt"

    func main() {
        messages := make(chan string)

        messages <- "my msg"

        select {
        case msg := <-messages:
            fmt.Println("received message", msg)
        }

    }
Run Code Online (Sandbox Code Playgroud)

上面的代码会出错

fatal error: all goroutines are asleep - deadlock!
Run Code Online (Sandbox Code Playgroud)

然而

如果我改成它

    package main

    import "fmt"

    func main() {
        messages := make(chan string)

        go func() {
            messages <- "my msg"
        }()
        select {
        case msg := <-messages:
            fmt.Println("received message", msg)
        }

    }
Run Code Online (Sandbox Code Playgroud)

它会工作.

这种行为有特殊原因吗?

代码不应该在第一种情况下以顺序方式执行,以便在达到select语句时,msg将被传递并且它将捕获大小写msg := <-messages

tka*_*usl 6

代码不应该在第一种情况下以顺序方式执行,以便在达到select语句时,msg将被传递并且它将捕获msg:= <-messages?

永远不会达到select语句,这就是第一个代码中的问题.

该声明

messages <- "my msg"
Run Code Online (Sandbox Code Playgroud)

想要将字符串推入通道,但是因为您创建了一个无缓冲的通道

messages := make(chan string)
Run Code Online (Sandbox Code Playgroud)

goroutine一直在等待某人实际从频道中读取,因此它可以将字符串推送到频道.如果某个地方有一个goroutine读取,你只能把东西推到一个无缓冲的通道!

尝试使用缓冲通道的第一个示例:

messages := make(chan string, 1)
Run Code Online (Sandbox Code Playgroud)

它应该按预期工作.