未初始化的通道如何表现?
Posted
技术标签:
【中文标题】未初始化的通道如何表现?【英文标题】:How does a non initialized channel behave? 【发布时间】:2016-12-25 05:32:58 【问题描述】:我有一个结构,其中包含一个未初始化的通道。
当我写入它时,例程按预期阻塞,但从未通知读者管道中有东西。
我很惊讶没有错误,我想知道 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 中发生了什么。)
【问题讨论】:
【参考方案1】:channel type 的“未初始化”字段或变量将具有所有通道类型的 zero value,即 nil
。那么让我们来看看nil
通道或对它的操作的行为。
值得在一篇文章中收集渠道公理:
nil
频道上的发送将永远阻塞 (Spec: Send statements)
来自nil
频道的接收将永远阻塞 (Spec: Receive operator)
发送到已关闭通道的错误 (Spec: Send statements)
来自关闭通道的接收立即返回零值 (Spec: Receive operator)
nil
通道阻塞的原因:如果通道值为nil
,则没有人引用它,所以没有人准备好接收它(我们想要发送的内容);或在其上发送任何内容(我们会从中收到什么)。
你可以在Dave Cheney: Channel Axioms阅读更多的推理和更多细节。
为了完整性:
Closingnil
频道会导致 run-time panic(就像关闭已经关闭的频道一样)。
一个nil
频道的Length and capacity是0
;根据nil
切片和具有0
长度和容量的映射。
推理:“关闭”是一种状态,但nil
频道不能有状态(nil
频道只有一个,“关闭”和“未关闭”频道没有一个)。并且nil
通道中没有排队的元素(所以 len = 0),并且它没有缓冲区容量(所以 cap = 0)。
【讨论】:
【参考方案2】:这是预期的行为。发送到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
【讨论】:
以上是关于未初始化的通道如何表现?的主要内容,如果未能解决你的问题,请参考以下文章