一尘不染

未初始化的通道表现如何?

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")
}

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

(我知道我应该初始化通道,这不是问题的目的,我想知道使用未初始化的通道在Go中发生了什么。)


阅读 329

收藏
2020-07-02

共1个答案

一尘不染

通道类型的“未初始化”字段或变量的所有通道类型的零值为nil。因此,让我们研究一下nil通道或通道上的操作。

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

nil通道阻塞的原因:如果一个通道值为nil,则没有人引用它,因此没有人会准备好从中接收(我们要发送的内容);或发送任何内容(我们会从中收到什么)。

您可以在Dave Cheney:Channel Axioms中阅读更多的推理和更多详细信息。

为了完整性:

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

理由:“关闭”是一种状态,但是一个nil通道不能具有状态(只有一个nil通道,“关闭”通道没有一个通道,“非关闭”通道没有一个通道)。而且没有元素在nil通道中排队(因此len
= 0),并且它没有缓冲区容量(因此cap = 0)。

2020-07-02