Go语言的缓冲通道和非缓冲通道

本文介绍了Go语言中非缓冲和缓冲通道的区别,包括它们的语法、发送和接收行为。重点讲解了非缓冲通道在通道同步中的应用以及缓冲通道如何实现生产者消费者模型,通过实例展示了其在控制生产者和消费者速度上的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Go语言中通道存在两种:非缓冲通道和缓冲通道。

非缓冲通道语法如下:

channel := make(chan type) // type 为通道类型(值可以为 string, int...)。

缓冲通道语法相比非缓冲通道多了一个参数,用于指定缓冲队列的大小。示例如下:

channel := make(chan type, size) // size 为队列大小。

非缓冲通道的发送和接收都是阻塞的。协程尝试从通道中拿数据会导致阻塞,直到有数据到达。协程向通道中发送数据也会导致阻塞,直到数据被提取。

缓冲通道有一个队列,队列大小取决于你指定的容量。发送操作会将数据放入队列尾部,接收操作会从队头取出数据。向一个满队列发送数据会导致阻塞,直到队列不满。从一个空队列取数据也会阻塞,直到队列不空。

我们可以简单得将非缓冲通道理解为队列容量为零的缓冲通道。

非缓冲通道有一种常见的用途就是通道同步。

示例如下:

package main

import (
	"fmt"
	"time"
)

func worker(done chan bool) {
	fmt.Println("working...")
    // 假装很忙,忙两秒。
	time.Sleep(2 * time.Second)
    // 忙完了。
	fmt.Println("finished")

    // 向通道发送任务完成信息
	done <- true
}

func main() {

    // 创建非缓冲通道
	done := make(chan bool)
    // 开启协程
	go worker(done)

    // 阻塞等待完成信息。
	<-done
}

上面的通道同步就是利用到了非缓冲通道接收信息时阻塞的特性。

缓冲通道有一个用途就是实现生产者消费者模型。利用缓冲通道的缓冲队列我们可以轻松实现生产者的异步发送和消费者的异步接收。

下面我们使用缓冲通道实现一个最基本的生产者消费者模型,示例如下:

package main

import (
	"fmt"
	"time"
)

// 生产者:向缓冲通道队列中生产数据。
func producer(message chan int) {
    var count int
	for {
		message <- count
		count++
	}
}

// 消费者:从缓冲通道队列中消费数据。
func consumer(message chan int) {
	for {
		fmt.Println("recv:", <-message)
	}
}

func main() {
    // 创建缓冲队列大小为200的缓冲通道。
	message := make(chan int, 200)

	go producer(message)
	go consumer(message)

    // 阻塞1s,给程序一定运行时间。
	time.Sleep(1 * time.Second)
}

在这个例子中,producer函数是生产者,它不断地向通道message发送整数。consumer函数是消费者,它不断地从通道message接收数据并打印。

当生产者的生产速度大于消费者的消费速度时,会将队列填满而阻塞生产。当消费者的消费速度大于生产者的生产速度时,会将队列耗空而阻塞消费。自然而然得控制住了生产者和消费者的处理速度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值