陈哈哈的博客

Go语言重点笔记-通道channel的用法

2018-06-05

一、Channel的特性

Channel是Go语言的一种数据类型,它与intstring类型一样。这里里,我们可以先将Channel理解为语言层面解决多线程读写问题的阻塞队列。

它具有与BlockingQueue相同的物性:

  1. 读操作时,如果队列为空,阻塞;
  2. 写操作时,如果队列为满,阻塞;
  3. 如果队列被关闭,队列内缓存的元素可以被读取,直到读完;

二、例子

以下是个精巧的例子,它演示了Channel作为阻塞队列用途,在Go语言中的惯用技巧。

例子的输出结果是:

Loop start
Loop received data: 0
Loop received data: 1
Loop received data: 2
Loop received data: 3
Loop received data: 4
Loop received data: 5
Loop received data: 6
Loop received data: 7
Loop received data: 8
Loop received data: 9
Loop completed
Demo finished

2.1 零长度Channel的阻塞与关闭

在演示例子中,零长度的Channel由于其处于空队列状态,在读操作上将会阻塞。
利用此特性,可以作为阻塞等待的信号:

waitStop := make(chan struct{})

/* ... */

close(waitStop)

当零长度Channel被Close后,它将立即返回,实现了解除阻塞的功能。

2.2 for-range读取Channel

for-range作用于Channel时,它将循环地读取Channel的数据,直到Channel被关闭,并且已读完所有缓存。

用Java语言来表述,类似于:

while (ch.isClosed() && ch.isEmpty()) {
String val = ch.pool();
/* do something */
}

根据上述演示代码,在等待协程启动时,调用time.Sleep(time.Second)暂停1秒。这个时间,让Goroutine启动起来,并完完全全地进入for-range循环。