未初始化的通道如何表现?
How does a non initialized channel behave?
我有一个包含未初始化通道的结构。
当我写入它时,例程按预期阻塞,但是 reader 从未被通知管道中有东西。
我很惊讶没有错误,我想知道 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
频道永远阻塞。您可以在此处的规范中阅读相关信息:https://golang.org/ref/spec#Send_statements
这同样适用于 nil
频道上的接收。 (https://golang.org/ref/spec#Receive_operator)
您也可以将此 link 放在手边以供参考:http://dave.cheney.net/2014/03/19/channel-axioms
所有渠道类型channel type will have the zero value的"uninitialized"字段或变量nil
。因此,让我们检查一下 nil
通道或其上的操作的行为方式。
通道公理值得收藏在一个post:
nil
通道上的发送永远阻塞(Spec: Send statements)
- 从
nil
频道接收永远阻塞 (Spec: Receive operator)
- a 发送到一个关闭的频道恐慌 (Spec: Send statements)
- a 从关闭的通道接收 returns 零值立即 (Spec: Receive operator)
nil
个频道阻塞的原因:如果一个频道值是 nil
,没有人引用它,所以没有人准备好从它接收(什么我们要发送);或发送任何东西(我们将从中收到什么)。
您可以在 Dave Cheney: Channel Axioms 中阅读更多推理和更多详细信息。
完整性:
- Closing a
nil
channel causes a run-time panic(就像关闭一个已经关闭的频道一样)。
nil
频道的 - Length and capacity 是
0
;根据具有 0
长度和容量的 nil
切片和映射。
推理:"closed"是一种状态,但是nil
通道不能有状态(只有一个nil
通道,"closed"和一个用于 "not closed" 频道)。并且 nil
通道中没有元素排队(因此 len = 0),并且它没有缓冲容量(因此 cap = 0)。
我有一个包含未初始化通道的结构。
当我写入它时,例程按预期阻塞,但是 reader 从未被通知管道中有东西。
我很惊讶没有错误,我想知道 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
频道永远阻塞。您可以在此处的规范中阅读相关信息:https://golang.org/ref/spec#Send_statements
这同样适用于 nil
频道上的接收。 (https://golang.org/ref/spec#Receive_operator)
您也可以将此 link 放在手边以供参考:http://dave.cheney.net/2014/03/19/channel-axioms
所有渠道类型channel type will have the zero value的"uninitialized"字段或变量nil
。因此,让我们检查一下 nil
通道或其上的操作的行为方式。
通道公理值得收藏在一个post:
nil
通道上的发送永远阻塞(Spec: Send statements)- 从
nil
频道接收永远阻塞 (Spec: Receive operator) - a 发送到一个关闭的频道恐慌 (Spec: Send statements)
- a 从关闭的通道接收 returns 零值立即 (Spec: Receive operator)
nil
个频道阻塞的原因:如果一个频道值是 nil
,没有人引用它,所以没有人准备好从它接收(什么我们要发送);或发送任何东西(我们将从中收到什么)。
您可以在 Dave Cheney: Channel Axioms 中阅读更多推理和更多详细信息。
完整性:
- Closing a
nil
channel causes a run-time panic(就像关闭一个已经关闭的频道一样)。 - Length and capacity 是
0
;根据具有0
长度和容量的nil
切片和映射。
nil
频道的 推理:"closed"是一种状态,但是nil
通道不能有状态(只有一个nil
通道,"closed"和一个用于 "not closed" 频道)。并且 nil
通道中没有元素排队(因此 len = 0),并且它没有缓冲容量(因此 cap = 0)。