Golang Concepts: Nil Channels
在 Go 中,通道是用于 goroutines 之间通信的核心特性。通道旨在用于消息共享,不过当我们使用 nil channel 时,有没有想到过为什么需要 nil channel 呢?
What are nil channels?
在 Go 中,nil 通道是已声明但未使用 make 语句初始化的通道,或显式设置为 nil。
一个 nil 通道具有以下属性:
-
从 nil 通道永久阻塞接收。
-
向 nil 通道永久阻塞发送。
-
关闭 nil 通道会引发 panic。
nil channel 有什么用?
让我们从涉及 channel 的基本示例开始,为我们探索 nil channel 的重要性铺平道路:

在上面的示例中,我们创建了两个 goroutine,它们分别在通道 a
和 b
上发送消息。在发送值完成后,它们还关闭了这些通道。
在主例程中,我们有一个无限循环来消耗来自通道的值。我们不关心处理的顺序,因此我们使用了一个 for..select
块来处理来自通道的值。
以下是上述程序的输出:
Received value from b: 10
Received value from b: 11
Received value from a: 0
Received value from b: 12
Received value from a: 1
Received value from b: 13
Received value from a: 2
Received value from b: 14
Received value from a: 3
Received value from b: 0
Received value from a: 4
Received value from b: 0
Received value from a: 0
Received value from b: 0
Received value from a: 0
Received value from b: 0
Received value from a: 0
...
Why?
一旦一个通道被关闭,并且其缓冲区中的所有值都被取出,该通道将始终立即返回零值。
所以,现在让我们通过从通道中获取打开的值来了解通道何时被关闭。

通过以上更改,虽然我们停止了打印零值,但我们仍然在无限循环中迭代一个已关闭的通道并打印相同的值。
Received value from b: 10
Received value from b: 11
Received value from a: 0
Received value from b: 12
Received value from a: 1
Received value from b: 13
Received value from a: 2
Received value from b: 14
Received value from a: 3
Received value from a: 4
Channel a is closed
Channel a is closed
Channel b is closed
Channel b is closed
...
现在,让我们尝试在我们知道通道已关闭时打破循环。我们可以通过利用两个变量,aClosed 和 bClosed,来实现这一点。

我们终于能够达到一个不再无限运行的位置。然而,如果你注意到,这里仍然多次打印 “Channel a is closed”。这导致了一些 CPU 循环的浪费!
Received value from b: 10
Received value from b: 11
Received value from a: 0
Received value from a: 1
Received value from a: 2
Received value from a: 3
Received value from a: 4
Received value from b: 12
Channel a is closed
Received value from b: 13
Channel a is closed
Channel a is closed
Received value from b: 14
Channel b is closed
Exiting.
当在 select 语句中使用多个通道操作时,如果其中一个通道被关闭,select 将立即解析到该通道,因为它可以立即接收(接收零值)。因此,我们会看到多次打印“Channel a is closed”的消息。
现在,让我们尝试将通道设置为 nil。在用于处理多个通道操作的 select 语句中,nil 通道实际上会被忽略(因为从 nil 通道接收会阻塞),因此我们不应该遇到因关闭通道而浪费 CPU 循环的问题。

现在就达到了完美的状态,不会再浪费任何 CPU 在循环里了。
Received value from b: 10
Received value from a: 0
Received value from b: 11
Received value from b: 12
Received value from a: 1
Received value from b: 13
Received value from b: 14
Channel b is closed
Received value from a: 2
Received value from a: 3
Received value from a: 4
Channel a is closed
Exiting.
原文始发于微信公众号(Go Official Blog):Golang Concepts: Nil Channels
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/259016.html