Go语言带缓冲的通道实现

 更新时间:2021年04月26日 11:43:03   投稿:zx  
这篇文章主要介绍了Go语言带缓冲的通道实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

Go语言中有缓冲的通道(buffered channel)是一种在被接收前能存储一个或者多个值的通道。这种类型的通道并不强制要求 goroutine 之间必须同时完成发送和接收。通道会阻塞发送和接收动作的条件也会不同。只有在通道中没有要接收的值时,接收动作才会阻塞。只有在通道没有可用缓冲区容纳被发送的值时,发送动作才会阻塞。

这导致有缓冲的通道和无缓冲的通道之间的一个很大的不同:无缓冲的通道保证进行发送和接收的 goroutine 会在同一时间进行数据交换;有缓冲的通道没有这种保证。

在无缓冲通道的基础上,为通道增加一个有限大小的存储空间形成带缓冲通道。带缓冲通道在发送时无需等待接收方接收即可完成发送过程,并且不会发生阻塞,只有当存储空间满时才会发生阻塞。同理,如果缓冲通道中有数据,接收时将不会发生阻塞,直到通道中没有数据可读时,通道将会再度阻塞。

无缓冲通道保证收发过程同步。无缓冲收发过程类似于快递员给你电话让你下楼取快递,整个递交快递的过程是同步发生的,你和快递员不见不散。但这样做快递员就必须等待所有人下楼完成操作后才能完成所有投递工作。如果快递员将快递放入快递柜中,并通知用户来取,快递员和用户就成了异步收发过程,效率可以有明显的提升。带缓冲的通道就是这样的一个“快递柜”。

创建带缓冲通道

如何创建带缓冲的通道呢?参见如下代码:

通道实例 := make(chan 通道类型, 缓冲大小)

  • 通道类型:和无缓冲通道用法一致,影响通道发送和接收的数据类型。
  • 缓冲大小:决定通道最多可以保存的元素数量。
  • 通道实例:被创建出的通道实例。

下面通过一个例子中来理解带缓冲通道的用法,参见下面的代码:

package main
import "fmt"
func main() {
    // 创建一个3个元素缓冲大小的整型通道
    ch := make(chan int, 3)
    // 查看当前通道的大小
    fmt.Println(len(ch))
    // 发送3个整型元素到通道
    ch <- 1
    ch <- 2
    ch <- 3
    // 查看当前通道的大小
    fmt.Println(len(ch))
}

代码输出如下:
0
3

代码说明如下:

  • 第 8 行,创建一个带有 3 个元素缓冲大小的整型类型的通道。
  • 第 11 行,查看当前通道的大小。带缓冲的通道在创建完成时,内部的元素是空的,因此使用 len() 获取到的返回值为 0。
  • 第 14~16 行,发送 3 个整型元素到通道。因为使用了缓冲通道。即便没有 goroutine 接收,发送者也不会发生阻塞。
  • 第 19 行,由于填充了 3 个通道,此时的通道长度变为 3。

阻塞条件

带缓冲通道在很多特性上和无缓冲通道是类似的。无缓冲通道可以看作是长度永远为 0 的带缓冲通道。因此根据这个特性,带缓冲通道在下面列举的情况下依然会发生阻塞:

  • 带缓冲通道被填满时,尝试再次发送数据时发生阻塞。
  • 带缓冲通道为空时,尝试接收数据时发生阻塞。

为什么Go语言对通道要限制长度而不提供无限长度的通道?

我们知道通道(channel)是在两个 goroutine 间通信的桥梁。使用 goroutine 的代码必然有一方提供数据,一方消费数据。当提供数据一方的数据供给速度大于消费方的数据处理速度时,如果通道不限制长度,那么内存将不断膨胀直到应用崩溃。因此,限制通道的长度有利于约束数据提供方的供给速度,供给数据量必须在消费方处理量+通道长度的范围内,才能正常地处理数据。

到此这篇关于Go语言带缓冲的通道实现的文章就介绍到这了,更多相关Go语言带缓冲通道内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • golang语法使用的注意事项

    golang语法使用的注意事项

    这篇文章主要给大家介绍了关于golang语法使用的一些注意事项,Golang是一种静态类型的编程语言,它支持基本的数据类型,包括整型、浮点型、布尔型、字符串型,需要的朋友可以参考下
    2023-07-07
  • Go之集合slice的实现

    Go之集合slice的实现

    本文主要介绍了Go之集合slice的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • 通过Golang编写一个AES加密解密工具

    通过Golang编写一个AES加密解密工具

    这篇文章主要为大家详细介绍了如何利用Golang制作一个AES加密解密工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2022-05-05
  • 深入解析Go 变量字符串与字符编码问题

    深入解析Go 变量字符串与字符编码问题

    Go的字符串是由单个字节连接起来的,Go语言的字符串的字节使用UTF-8编码标识Unicode文本,接下来通过本文给大家介绍下Go变量字符串与字符编码问题,需要的朋友可以参考下
    2022-04-04
  • Golang Type关键字的使用

    Golang Type关键字的使用

    Type关键字在Go语言中作用很重要,比如定义结构体,接口,还可以自定义类型,定义类型别名等,具有一定的参考价值,感兴趣的可以了解一下
    2023-11-11
  • golang cobra使用chatgpt qdrant实现ai知识库

    golang cobra使用chatgpt qdrant实现ai知识库

    这篇文章主要为大家介绍了golang cobra使用chatgpt qdrant实现ai知识库,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • go带缓冲chan实现消息队列功能

    go带缓冲chan实现消息队列功能

    本文主要介绍了go带缓冲chan实现消息队列功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • Go语言的管道Channel用法实例

    Go语言的管道Channel用法实例

    这篇文章主要介绍了Go语言的管道Channel用法,实例分析了Go语言中管道的原理与使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-02-02
  • Golang::slice和nil的对比分析

    Golang::slice和nil的对比分析

    这篇文章主要介绍了Golang::slice和nil的对比分析,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • 一文搞懂Go语言操作Redis的方法

    一文搞懂Go语言操作Redis的方法

    Redis是一个开源的内存数据库,在项目开发中redis的使用也比较频繁,本文介绍了Go语言中go-redis库的基本使用。感兴趣的小伙伴们可以参考借鉴一下
    2022-09-09

最新评论