Go并发基础 | 青训营笔记

130 阅读1分钟

channel 管道

channel是通过通信的方式来共享内存,而不是通过共享内存来通信

channel创建

Channel是引用类型,声明方式如下:

ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) ElementType .

其中:

  • chan channel类型关键字

  • <- 操作符,用于Channel收发,定义Channel类型时,用于表示Channel的方向:

    • 默认是双向,可收可发。还可以定义为定向的,仅收仅发。
    • chan<- 仅发送Channel
    • <-chan 仅接收Channel
  • ElementType Channel中元素类型

ch := make(chan int)
var ch = make(chan int)
ch := make(chan int, 10) // 定义一个容量为10的缓冲管道
ch := make(<-chan int)  // 只读
ch := make(chan<- int, 10)  // 只可以写

未使用make()初始化的 channel 为 nil 。nil channel不能执行收发通信操作,例如:

var ch chan int // nil

ch就是nil channel。

Send语句语法:

SendStmt = Channel "<-" Expression .
Channel  = Expression .
ch <- Expression
ch <- 42
ch <- f()

接收操作符语法

<-ch
v1 := <-ch // 声明
v = <-ch   // 赋值
f(<-ch)   // 函数调用
<-strobe // 等待接收

channel关闭

通过close(ch)关闭管道。

关闭Channel的意思是记录该Channel不能再被发送任何元素了「不能再向管道放数据」,而不是销毁该Channel的意思。也就意味着关闭的Channel是可以继续接收值的「可以从管道拿出数据」。因此:

  • 向已关闭的Channel发送会引发runtime panic
  • 关闭nil Channel会引发runtime panic
  • 不能关闭仅接收Channel
  • 不能关闭已经关闭的Channel,否则会引发runtime panic

当从已关闭的Channel接收时:

  • 可以接收关闭前发送的全部值
  • 若没有已发送的值会返回类型的零值,不会被阻塞

使用接收操作符的多值返回结构,可以判断Channel是否已经关闭:

var x, ok = <-ch
x, ok := <-ch
  • ok为true,channel未关闭
  • ok为false,channel已关闭

缓冲和无缓冲channel

Channel区别于是否存在缓冲区,分为:

  • 缓冲Channel,make(chan T, cap),cap是大于0的值。

    适合用于goroutine的通信

  • 无缓冲Channel, make(chan T), make(chan T, 0)

    适合做goroutine的信号

单向channel

单向Channel,指的是仅支持接收或仅支持发送操作的Channel。语法上:

  • chan<- T 仅发送Channel
  • <-chan T 仅接收Channel

单向Channel的意义在于约束Channel的使用方式。

仅使用单向Channel通常没有实际意义,单向Channel最典型的使用方式是:

使用单向通道约束双向通道的操作。

语法上来说,就是我们会将双向Channel转换为单向Channel来使用。典型使用在函数参数或返回值类型中