引言
在上篇goroutine资源竞争部分,我提出了主线程和协程间的结束问题,由此我们可以引出解决办法channel(管道)
介绍
channel的本质就是一种队列,是一种数据结构。数据在管道中先进先出(FIFO:first in first out)。管道也是有数据类型的,如int类型的channel只能存放int类型的数据。
入门
基本语法:var 变量名 chan 数据类型。
- channel是引用类型。
- channel必须
make后才能使用。 - channel只能放定义的数据类型。
make的使用方法:变量名 = make (chan 数据类型,容量)。channel的容量并不会变化,如果我们容量定为3,那么往里加的的数据最多就是3个,超过则会报错。
向管道写入数据:管道名<- 需要写入的变量(或值)示例:
var intChan chan int //定义int类型的管道
var num int = 15
intChan = make (chan int, 3) //初始化
intChan<- 3 //写入数据
intChan<- num //写入数据
向管道中读取数据:变量名 = <-管道名。注:如果管道数据都取完了,还在继续取,编译就会报错。延续上面代码进行演示(因为管道是先进先出,所以下面代码的num2应该是3):
var num2 int
num2 = <-intChan
假如我想要第二个数据,第一个数据我又不想定义个变量去存放,我们就可以直接输入<-intChan实现,即把数据推出。
channel的关闭和遍历
channel的关闭
我们可以使用内置的close语句实现管道的关闭。关闭后的管道就不能再往里面继续写入数据,但仍然可以读取数据。语法是:close(管道变量名)。
channel的遍历
下面我们将使用for range语句对管道遍历。但前提是管道必须已经关闭,如果没有关闭则会报错。因为它不知道什么时候结束,会一直遍历,就会报deadlock的错误。
close(intChan)
for v:= range intChan{
fmt.Println("v=",v)
}
重点:管道遍历的返回值只有value,因为管道是先进先出,所以它没有下标。