Channel

AI摘要
【知识分享】本文介绍了Go语言中channel的基本概念、使用规则及遍历方法。内容涵盖:向nil或已关闭channel发送消息的后果、channel关闭后的接收行为、使用for range和select进行channel遍历的两种方式,并提供了完整代码示例。属于技术知识分享,无违规内容。

Channel

从字面上看,channel的意思大概就是管道的意思。channel是一种go协程用以接收或发送消息的安全的消息队列,channel就像两个go协程之间的导管,来实现各种资源的同步。可以用下图示意:
Channel

  • 向一个nil channel发送消息,会一直阻塞;
  • 向一个已经关闭的channel发送消息,会引发运行时恐慌(panic)
  • channel关闭后不可以继续向channel发送消息,但可以继续从channel接收消息;
  • channel关闭并且缓冲区为空时,继续从从channel接收消息会得到一个对应类型的零值。

Channel的遍历

package main 

import ( 
    "fmt" 
) 

func main() { 
    c := make(chan int) 

    go func() { 
        for i := 0; i < 10; i++ { 
            c <- i 
        } 
        close(c) 
    }() 

    for v := range c { 
        fmt.Printf("v: %v\n", v) 
    } 
} 

在遍历时,如果channel 没有关闭,那么会一直等待下去,出现 deadlock 的错误;如果在遍历时channel已经关闭,那么在遍历完数据后自动退出遍历。也就是说,for range 的遍历方式时阻塞型的遍历方式。

package main

import "fmt"

func main() {
    ci := make(chan int, 2)
    for i := 1; i <= 2; i++ {
        ci <- i
    }
    close(ci)
    cs := make(chan string, 2)
    cs <- "hi"
    cs <- "golang"
    close(cs)
    ciClosed, csClosed := false, false
    for {
        if ciClosed && csClosed {
            return
        }
        select {
        case i, ok := <-ci:
            if ok {
                fmt.Println(i)
            } else {
                ciClosed = true
                fmt.Println("ciclosed")
            }
        case s, ok := <-cs:
            if ok {
                fmt.Println(s)
            } else {
                csClosed = true
                fmt.Println("csclosed")
            }
        default:
            fmt.Println("waiting...")
        }
    }
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
Felix0417
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

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