概述

Channel 是Golang 在语言级别提供的goroutine 之间的通信方式。
注意:Channel 是进程内的通信方式,因此通过 channel 传递对象的过程和调用函数时的参数传递行为比较一致,比如也可以传递指针等。使用通道发送和接收所需的共享资源,可以在 goroutine 之间消除竞争条件。一个channel 只能传递一个类型的值,这个类型需要在声明channel的时候指定。

设计原理

设计模式:不要通过共享内存的方式进行通信,而是应该通过通信的方式共享内存。
channel设计模式.png
在Go语言中提供通信顺序进程(Communicating sequential processes,CSP)
CSP并发模型是上个世纪七十年代提出来的,用于描述两个独立的并发实体通过共享内存通讯进行通讯的并发模型。在Golang中并没有完全实现CSP模型的所有理论,仅仅借用process和channel这两个概念。在golang 中process(goroutine实际执行并发的实体),实体间通过channel实现共享数据。
channel通信.png
数据结构

  1. type hchan struct {
  2. // chan 里元素数量
  3. qcount uint
  4. // chan 底层循环数组的长度
  5. dataqsiz uint
  6. // 指向底层循环数组的指针
  7. // 只针对有缓冲的 channel
  8. buf unsafe.Pointer
  9. // chan 中元素大小
  10. elemsize uint16
  11. // chan 是否被关闭的标志
  12. closed uint32
  13. // chan 中元素类型
  14. elemtype *_type // element type
  15. // 已发送元素在循环数组中的索引
  16. sendx uint // send index
  17. // 已接收元素在循环数组中的索引
  18. recvx uint // receive index
  19. // 等待接收的 goroutine 队列
  20. recvq waitq // list of recv waiters
  21. // 等待发送的 goroutine 队列
  22. sendq waitq // list of send waiters
  23. // 保护 hchan 中所有字段
  24. lock mutex
  25. }

创建channel

  1. // 创建带缓存的channel
  2. ch := make(chan int, 10)
  3. // 创建不带缓存的channel
  4. ch := make(chan int)

发送数据

  1. // 发送数据
  2. ch <- i

发送数据是怎样的一个过程
https://golang.design/go-questions/channel/send/

接收数据

  1. // 接收数据
  2. i <- ch
  3. i,ok <- ch

关闭channel

  1. // 关闭 channel
  2. close ch