Golang Concepts: Nil Channels

Golang Concepts: Nil Channels

在 Go 中,通道是用于 goroutines 之间通信的核心特性。通道旨在用于消息共享,不过当我们使用 nil channel 时,有没有想到过为什么需要 nil channel 呢?

What are nil channels?

在 Go 中,nil 通道是已声明但未使用 make 语句初始化的通道,或显式设置为 nil。

一个 nil 通道具有以下属性:

  1. 从 nil 通道永久阻塞接收。

  2. 向 nil 通道永久阻塞发送。

  3. 关闭 nil 通道会引发 panic。

nil channel 有什么用?

让我们从涉及 channel 的基本示例开始,为我们探索 nil channel 的重要性铺平道路:

Golang Concepts: Nil Channels

在上面的示例中,我们创建了两个 goroutine,它们分别在通道 ab 上发送消息。在发送值完成后,它们还关闭了这些通道。

在主例程中,我们有一个无限循环来消耗来自通道的值。我们不关心处理的顺序,因此我们使用了一个 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?

一旦一个通道被关闭,并且其缓冲区中的所有值都被取出,该通道将始终立即返回零值。

所以,现在让我们通过从通道中获取打开的值来了解通道何时被关闭。

Golang Concepts: Nil Channels

通过以上更改,虽然我们停止了打印零值,但我们仍然在无限循环中迭代一个已关闭的通道并打印相同的值。

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,来实现这一点。

Golang Concepts: Nil Channels

我们终于能够达到一个不再无限运行的位置。然而,如果你注意到,这里仍然多次打印 “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 循环的问题。

Golang Concepts: Nil Channels

现在就达到了完美的状态,不会再浪费任何 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

(0)
土豆大侠的头像土豆大侠

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!