Go

Golang的特性二(通道)---channel的用法

Royal
2023-07-21 / 0 评论 / 8 阅读 / 正在检测是否收录...

1. 什么是channel?
channel的中文意思就是通道。在go中channel主要是用于协程之间的通信。
channel可以在同一时间保证只有一个携程在操作,从而避免了数据的竞争,实现的同步操作。

2. channel使用

  • 在go中,channel需要使用make函数进行内存分配。可以使用make函数,指定缓冲区的大小。

    ch := make(chan int,6)
  • 如果不指定缓冲区,则成为无缓冲区通道。该通道只有sender和receiver都准备好时,才能进行通信。

    func pump(ch chan int)  {
        for i := 1;;i++ {
            ch <- i
        }
    }
    
        ch1 := make(chan int) // 无缓冲通道
        go pump(ch1)
    

    以上程序没有receiver,程序会报错。因为通道是没有缓冲区的。当sender发送一个数据的时候,必须有receiver接收数据,这样sender才能继续发送数据。类似于生产者->消费者问题

    func pump(ch chan int)  {
        for i := 1;;i++ {
            ch <- i
        }
    }
    
        ch1 := make(chan int) // 无缓冲通道
        go pump(ch1)
        fmt.Println(<-ch1) // 这里只接收的到发送的第一个数据1。
    

    m7g5ldft.png

  • 发送、接收数据
    根据 <- 的流向,来判断是向通道发送数据,还是读取通道中的数据

        ch  := make(chan int,1)
        ch <- 10 // 向ch通道发送数据
    
        ch  = make(chan int,1)
        ch <- 10
        x := <- ch // 读取ch通道中的数据,并复制给x变量。
    

    注意:
    不能向已经满了的通道发送数据,否则会造成阻塞。

        ch  = make(chan int,2)
        ch <- 10
        ch <- 20
        ch <- 30 // 通道缓冲区大小为2,已满,不能再发送数据
    

    m7g5sx7x.png
    该错误告诉我们,所有的线程都已经休眠。则没有一个线程在运行,发生死锁。

  • 关闭通道

    close(ch) // 使用该方法关闭通道
    

    只有发送者可以关闭通道。 关闭的通道,在无数据的情况下,会返回false。否则是true。

  • 读取通道中的数据
    for range 可以读取通道中的数据,直到通道关闭

    for range
    

    例如:

        for v := range ch1 {
            fmt.Printf("%v",v)
        }
    

    m7g65bdx.png

3. 单通道
顾名思义,就是单向的通道,也就是只能接受或者发送的通道。

  • 只能接收

    var ch <- chan int
  • 只能发送

    var ch chan <- int

    4. select
    不同于switch,select只能用于io操作,一般配合channel使用。
    例如:

            select {
                case msg1 := <-c1:
                    fmt.Println("c1 received:",msg1)
                case msg2 := <-c2:
                    fmt.Println("c2 received",msg2)
                default:
                    fmt.Println("No data received")
            }
    

    m7g6gr74.png

以上例子中,只要一个通道里有数据,就会执行case。

如果没有匹配的case,且没有default语句。那么select会阻塞,直到某一case可以执行

与switch的主要区别:

switch的case是顺序匹配执行的。而select是随机执行的。

select中表达式必须是和通道有关的操作。

0

评论

博主关闭了当前页面的评论