对 channel 进行读、写、关闭操作会怎么样 ?

  • 对 nil 的 channel 进行读和写 都会造成当前 goroutine 永久阻塞(如果当前 goroutine 是 main goroutine,则会让整个程序直接报 fatal error 退出),关闭则会发生 panic(但这里我们不要忘记,还有一种叫做非阻塞(select default )的方式操作 channel,这种模式下,就算对为 nil 的 channel 读写,也不会阻塞的)

  • 对不为 nil,并且未关闭的 channel 操作,读和写都有两种情况:

    1. 读操作:
      成功读取:如果 channel 中有数据,直接从 channel 里面读取,如果此时写等待队列里面有 goroutine,还需要将队列头部 goroutine 数据写入到 channel 中,并唤醒这个 goroutine;如果 channel 没有数据,就尝试从写等待队列中读取数据,并做对应的唤醒操作

      (读操作无法及时完成)阻塞挂起:channel 里面没有数据 并且 写等待队列为空,则当前 goroutine 加入 读 i.等待队列中,并挂起,等待唤醒

    2. 写操作
      成功写入:如果 channel 读等待队列不为空,则取 头部 goroutine,将数据直接复制给这个头部 i.goroutine,并将其唤醒,流程结束;否则就尝试将数据写入到 channel 环形缓冲中

      (写操作无法及时完成)阻塞挂起:通道里面 buf 满了 并且 读等待队列为空,则当前 gorotine 加入写等待队 i.列中,并挂起,等待唤醒

  • 对已经关闭的 channel 进行写和关闭 都会导致 panic,而读取是直到读完 channel 中剩余数据,还想读的话,就会获得零值

  • select 分为两种,包含非阻塞型 select (包含 default 分支的)和阻塞型 select (不包含 default 分支的)

阻塞型:

package main

func main(){
    ch:=make(chan int)
    select {
    case <-ch:

    case ch<-1:
    }
}

非阻塞型:

package main

func main(){
    ch := make(chan int)
        select {
        case <-ch:

        case ch <- 1:

        default:

        }
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
微信搜索:上帝喜爱笨人
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!