我有一个包含未初始化通道的结构。
当我向它写入内容时,该例程将按预期方式阻塞,但是永远不会通知读者管道中有东西。
我很惊讶没有错误,我想知道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中发生了什么。)
通道类型的“未初始化”字段或变量的所有通道类型的零值为nil
。因此,让我们研究一下nil
通道或通道上的操作。
值得 在一篇文章中收集 渠道公理 :
nil
通道阻塞的原因:如果一个通道值为nil
,则没有人引用它,因此没有人会准备好从中接收(我们要发送的内容);或发送任何内容(我们会从中收到什么)。
您可以在Dave Cheney:Channel Axioms中阅读更多的推理和更多详细信息。
为了完整性:
理由:“关闭”是一种状态,但是一个nil
通道不能具有状态(只有一个nil
通道,“关闭”通道没有一个通道,“非关闭”通道没有一个通道)。而且没有元素在nil
通道中排队(因此len
= 0),并且它没有缓冲区容量(因此cap = 0)。