go - 未初始化的 channel 如何表现?

标签 go null initialization channel

我有一个包含未初始化 channel 的结构。

当我写入它时,例程按预期阻塞,但读者永远不会收到管道中有内容的通知。

我很惊讶没有错误,我想知道 Go 在做什么。

在下面的示例中,消息 pushedgot 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")
}

这里是 Playground https://play.golang.org/p/76zrCuoeoh

(我知道我应该初始化 channel ,这不是问题的目的,我想知道在没有初始化 channel 的情况下 Go 中发生了什么。)

最佳答案

channel type 的“未初始化”字段或变量会有 zero value所有 channel 类型的 nil。因此,让我们检查一个 nil channel 或它的操作是如何运行的。

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

nil channel 情况下阻塞的原因:如果 channel 值为 nil,则没有人引用它,因此没有人准备好接收来自它(我们要发送的内容);或发送任何东西(我们将从中收到什么)。

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

为了完整性:

  • Closing nil channel 导致 run-time panic (就像关闭一个已经关闭的 channel 一样)。
  • Length and capacity nil channel 的值为 0;根据具有 0 长度和容量的 nil slice 和映射。

推理:“closed”是一种状态,但是 nil channel 不能有状态(只有一个 nil channel ,没有一个用于“closed”和一个用于“未关闭” channel )。并且 nil channel 中没有排队的元素(因此 len = 0),并且它没有缓冲容量(因此 cap = 0)。

关于go - 未初始化的 channel 如何表现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39015602/

相关文章:

mysql - 检查两列之间的每一行中是否只存在一个空值 MySql(版本 8.0.13)

objective-c - 初始化属性,点符号

c - 声明 BufferData Data[16] = {0} 是什么意思

iphone - 在未初始化的对象(空指针)上调用方法

go - 函数指针作为参数, "return interface{}"

php - 在 Golang 中获取所有 Stripe 计划的数组

rest - 如何使用 Golang 实现导入数据功能?

Go 无法调用 NewRouter() 函数

ruby-on-rails - :default => 0 and :null => false differ for integer fields in migrations? 怎么办

c++ - 在 std vector 中查找 NULL 指针