go有缓冲channel和无缓冲channel

我们都知道通道(channel)分两种:

  1. 缓冲通道
  2. 非缓冲通道
    // 缓冲通道
    ch1 := make(chan int, 10)
    ch2 := make(chan bool, 2)
    
    
    // 非缓冲通道
    ch3 := make(chan int)
    ch4 := make(chan bool, 0)

发送通道数据

// 创建一个空接口通道,注意定义的通道类型有
ch := make(chan interface{})
// 将0放入通道中
ch <- 0
// 将hello字符串放入通道中
ch <- "hello"

接收通道数据

  1. 阻塞接收数据

    data := <-ch

    执行该语句时将会阻塞,直到接收到数据并赋值给 data 变量。

  2. 非阻塞接收数据

    // data:表示接收到的数据。未接收到数据时,data 为通道类型的零值
    // ok:表示是否接收到数据。
    data, ok := <-ch

    非阻塞的通道接收方法可能造成高的 CPU 占用,因此使用非常少。如果需要实现接收超时检测,可以配合 select 和计时器 channel 进行,可以参见后面的内容。

  3. 接收任意数据,忽略接收的数据

    <-ch
  4. 循环接收

    package main
    
    import (
        "fmt"
        "time"
    )
    
    func main() {
        ch := make(chan int)
        // 开启一个并发匿名函数
        go func() {
            for i := 3; i >= 0; i-- {
                ch <- i
                time.Sleep(time.Second)
            }
        }()
    
        // 遍历接收通道数据
        for data := range ch {
            fmt.Println(data)
            if data == 0 {
                break
            }
        }
    }

关闭通道

ch := make(chan string)

...

close(ch)

通道特性:

  1. 同一个通道,发送操作之间是互斥的,接收操作之间也是互斥的(并发安全)
  2. 发送操作和接收操作中对元素值的处理都是不可分割的。
  3. 发送操作在完全完成之前会被阻塞,接收操作也是一样。
  4. 对于缓冲通道:如果通道已满,那么对它的所有发送操作都会被阻塞,直到通道中有元素值被接收走;如果通道已空,那么对它的所有接收操作都会被阻塞,直到通道中有新的元素值出现。
    对于非缓冲通道:无论是发送操作还是接收操作,一开始执行就会被阻塞,直到配对的操作也开始执行,才会继续传递。

注意点:

关闭通道要在发送方关闭,关闭后如果channel内还有元素,并不会对接下来的接收产生影响
单向通道最主要的用途就是约束其他代码的行为
通过函数的参数类型或者返回值类型来限制(Go的语法糖)。

func(ch chan<- int) //传入双向通道,在函数里面调用ch只能发送
func() (ch <-chan int) //返回双向通道,在函数外面里面调用ch只能接收

那么非缓冲通道是不是就是缓冲size为1的缓冲通道呢?我们来测试下:

func TestChan(t *testing.T) {
	ch := make(chan int)
	ch <- 1
	go func() {
		<-ch
	}()
	ch <- 2
}

func TestChan2(t *testing.T) {
	ch := make(chan int, 1)
	ch <- 1
	go func() {
		<-ch
	}()
	ch <- 2
}

go test 运行一下,会发现TestChan阻塞住了,ch <- 1 不能写在go func 前面,那么非缓冲通道显然不是就是缓冲size为1的缓冲通道。非缓冲通道像是以前的快递员,必须有收货人当面接收成功,否则他会等着你送货,有缓冲通道更像是现在的快递员,直接放在驿站或者快递柜,除非驿站快递柜满了,否则他就胡塞,不管你在不在家,有没有接收成功。


go有缓冲channel和无缓冲channel
https://blog.puresai.com/2022/01/11/382/
作者
puresai
许可协议