Golang channel

本文介绍golang的channel的基础知识和一些经典的应用范式.

channel 基础

channel分类

  • buffered/unbuffered channel

按这个标准channel可以分为两个大类:带缓冲(buffered)的channel和不带缓冲(unbuffered)的channel. 定义一个不带缓的channel

var ch = make(chan bool)

下面这段代码会输出什么?

package main

func main(){
  ch :=make(chan int)
  ch <-10
  go task(ch)
}
func task(ch chan int){
   <- ch
}

答案是会死锁。因为unbuffered channel在写入数据之前需要有接收channle数据的goroutine做好准备。需要对上面代码做如下修改:

package main

func main(){
  ch :=make(chan int)
  go task(ch)
  ch <-10
}
func task(ch chan int){
   <- ch
}

带有缓冲的channel

var ch = make(chan bool, 3)
  • unidirectoinal/bidirectional channel

定义一个双向(bidirectional)channel

var ch = make(chan bool)

双向的意思是可以在channel上读或者写. 定义一个单向只读channel

var ch = make(<- chan bool)

定义一个单向只写channel

var ch = make(chan <- bool)

channel的状态

对处于不同状态的channel的读写操作会有不同的结果

  • nil

对nil状态的channel读写都会被阻塞,造成死锁。

  • open

对正常open状态的channel可以进行正常读写。

  • closed

往closed状态的channel写数据会造成panic,但是读取不会造成panic,会得到channel类型的零值。

channel的实现原理

实现channel的关键数据结构

 type hchan struct {
    qcount   uint           // total data in the queue
    dataqsiz uint           // size of the circular queue
    buf      unsafe.Pointer // points to an array of dataqsiz elements
    elemsize uint16
    closed   uint32
    elemtype *_type // element type
    sendx    uint   // send index
    recvx    uint   // receive index
    recvq    waitq  // list of recv waiters
    sendq    waitq  // list of send waiters

    // lock protects all fields in hchan, as well as several
    // fields in sudogs blocked on this channel.
    //
    // Do not change another G's status while holding this lock
    // (in particular, do not ready a G), as this can deadlock
    // with stack shrinking.
    lock mutex
}

channel里包含一个环形队列,用于将goroutine发送的数据保存到队列中。另外 recvqsendq 队列用于保存阻塞在读和写操作的goroutine. 当channel中有数据可读或可写时,调度器唤醒阻塞在相应队列中的goroutine.

channle常用的应用范式

  1. 生产者消费者模式
  2. 一对多和多对一的通知
  3. 互斥锁
  4. ratelimiting
  5. 限制并发数
  6. 配合select超时控制

参考链接

  • channel 各个状态下的读写行为
  • channel 的实现原理
  • 使用 channel 的各种骚操作
  • The Behavior Of Channels
  • Why using unbuffered channel in the same goroutine gives a deadlock
  • Curious Channels
  • rate limiting

你可能感兴趣的:(Golang channel)