非初始化通道如何表现?

pou*_*sma 5 null initialization channel go

我有一个结构,包含一个未初始化的通道.

当我写入它时,例程会按预期阻塞,但读者永远不会被告知管道中存在某些内容.

我很惊讶没有错误,我想知道Go是做什么的.

在下面的示例中,既不显示消息pushed也不got it打印.(取消注释初始化,它将像魅力一样工作)

type MyStruct struct {
    over chan bool
}

func main() {
    nonInitialized := &MyStruct{}
    // nonInitialized.over = make(chan bool)
    go func() {
        for i := 0; i < 10; i++ {
            select {
            case <-nonInitialized.over:
                fmt.Println("got it")
            default:
                // proceed
            }
            fmt.Println("do some stuff")
            time.Sleep(10 * time.Millisecond)
        }
        panic("took too long")
    }()
    // push on the non initialized channel
    fmt.Println("pushing")
    nonInitialized.over <- true
    fmt.Println("pushed")
}
Run Code Online (Sandbox Code Playgroud)

这是游乐场https://play.golang.org/p/76zrCuoeoh

(我知道我应该初始化频道,这不是问题的目的,我想知道Go中发生的事情与未初始化的频道.)

icz*_*cza 10

"未初始化"字段或通道类型的变量将具有所有通道类型的零值nil.因此,让我们来看看它上面的nil通道或操作是如何运作的.

值得在一篇文章中收集频道公理:

在nil频道情况下阻止推理:如果频道值是nil,没有人有参考,那么没有人愿意接收它(我们想要发送的东西); 或发送任何东西(我们将从中收到的东西).

你可以在Dave Cheney中看到进一步的推理和更多细节:Channel Axioms.

为了完整性:

  • 关闭一个nil频道将会引起一个运行时恐慌(就像闭一个已经封闭的通道).
  • 长度和容量一个的nil信道是0; 根据nil具有0长度和容量的切片和地图.

推理:"关闭"是一种状态,但是一个nil通道不能具有状态(只有一个nil通道,而不是一个用于"关闭"而一个用于"未关闭"通道).并且没有在nil通道中排队的元素(因此len = 0),并且它没有缓冲容量(所以cap = 0).