golang channel 学习笔记

一、 chan 的类型

channel类型是可以带有方向的,假设T是一种类型:

  • chan T是双向channel类型,编译器允许对双向channel同时进行发送和接收。
  • chan<- T是只写channel类型,编译器只允许往channel里面发送数据。
  • <-chan T是只读channel类型,编辑器只允许从channel里面接收数据。

双向类型的channel,可以被强制转换成只读channel或者是只写channel,但是反过来却不行,只读和只写channel是不可以转换成双向channel的。

二、 chan 的初始化

channel里面的value buffer的容量也就是channel的容量。channel的容量为零表示这是一个阻塞型通道,非零表示缓冲型通道[非阻塞型通道]。

三、内部结构

每个channel内部实现都有三个队列

  • 接收消息的协程队列。这个队列的结构是一个限定最大长度的链表,所有阻塞在channel的接收操作的协程都会被放在这个队列里。
  • 发送消息的协程队列。这个队列的结构也是一个限定最大长度的链表。所有阻塞在channel的发送操作的协程也都会被放在这个队列里。
  • 环形数据缓冲队列。这个环形数组的大小就是channel的容量。如果数组装满了,就表示channel满了,如果数组里一个值也没有,就表示channel是空的。对于一个阻塞型channel来说,它总是同时处于即满又空的状态。

四、相关操作

五、select-case

上面这段代码中,select 语句有四个 case 子语句,前两个是 receive 操作,第三个是 send 操作,最后一个是默认操作。代码执行到 select 时,case 语句会按照源代码的顺序被评估,且只评估一次,评估的结果会出现下面这几种情况:

  • 除 default 外,如果只有一个 case 语句评估通过,那么就执行这个case里的语句;
  • 除 default 外,如果有多个 case 语句评估通过,那么通过伪随机的方式随机选一个;
  • 如果 default 外的 case 语句都没有通过评估,那么执行 default 里的语句;
  • 如果没有 default,那么 代码块会被阻塞,指导有一个 case 通过评估;否则一直阻塞

下面会随机输出 v1, v2

下面会循环输出全部,直至主进程销毁。

超时设定