我有一个结构,它包含一个未初始化的通道。
当我写入时,例程会按预期阻塞,但读者永远不会被告知管道中存在某些内容。
我很惊讶没有错误,我想知道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中有非初始化频道发生了什么。)
答案 0 :(得分:9)
channel type的“未初始化”字段或变量将包含nil
所有频道类型的zero value。因此,让我们来看看nil
频道或其上的操作是如何运作的。
值得在一篇文章中收集频道公理:
nil
频道上的发送永久阻止(Spec: Send statements)nil
频道的接收永久阻止(Spec: Receive operator)在nil
频道的情况下阻止推理:如果频道值为nil
,则没有人对其进行引用,因此没有人愿意接收它(我们想要的是什么)发送);或发送任何东西(我们将从中收到的东西)。
您可以在Dave Cheney: Channel Axioms中阅读更多有关此内容的推理和更多详情。
完整性:
nil
频道会导致run-time panic(就像关闭已经关闭的频道一样)。nil
频道的0
;根据{{1}}切片和具有nil
长度和容量的地图。推理:“已关闭”是一种状态,但0
频道不能拥有状态(只有一个nil
频道,而不是一个用于“已关闭”,另一个用于“未关闭”渠道)。并且在nil
通道中没有排队的元素(因此len = 0),并且它没有缓冲容量(所以cap = 0)。
答案 1 :(得分:4)
这是预期的行为。发送到nil
频道会永久阻止。您可以在此处的规范中阅读相关内容:https://golang.org/ref/spec#Send_statements
同样适用于nil
频道的接收。 (https://golang.org/ref/spec#Receive_operator)
您也可以将此链接放在手边以供参考:http://dave.cheney.net/2014/03/19/channel-axioms