草庐IT

Go 快速入门指南 - 缓冲通道和非缓冲通道

洋芋土豆 2023-03-28 原文

概述

建议先阅读 goroutine 小节。

Go 箴言: 不要通过共享内存来通信,而要通过通信来共享内存。

goroutine 是 Go 程序并发执行的实体,channel (通道) 则是它们之间的连接,用于多个 goroutine 之间互相通信。通道可以让一个 goroutine 发送特定类型值到另一个 goroutine,每一个通道可以发送数据类型称为通道的 元素类型

阻塞通道与非阻塞通道

通过关键字 chan + 数据类型 来表明通道数据类型,调用 make() 函数来初始化一个通道。 make() 函数的第二个参数为通道长度,如果未指定或指定为 0,则该通道为非缓存通道 (阻塞通道), 否则该通道为缓存通道 (非阻塞通道)。

阻塞通道

图片来源: https://stackoverflow.com/questions/39826692/what-are-channels-used-for

例子

ch := make(chan string) // 非缓冲通道
ch := make(chan string, 0) // 非缓冲通道
ch := make(chan string, 10) // 缓冲通道, 容量为 10

3 种操作

发送

无缓冲通道上面的发送操作将会阻塞,直到另一个 goroutine 在对应的通道上面完成接收操作,两个 goroutine 才可以继续执行。

语法规则

通道变量 <- 数据

# 例如: 将变量 x 发送到通道 ch
ch <- x 

接收

无缓冲通道上面的接收操作将会阻塞,直到另一个 goroutine 在对应的通道上面完成发送操作,两个 goroutine 才可以继续执行。

语法规则

<- 通道变量

# 例如: 从通道 ch 接收一个值,并且丢弃
<-ch 
接收变量 <- 通道变量

# 例如: 从通道 ch 接收一个值,并且赋值给变量 x
x := <-ch 

关闭

详情见 关闭通道。

例子

搭配 goroutine

package main

func main() {
    ch := make(chan string) // 没有设置通道的长度

    go func() {
        ch <- "hello world"
    }()

    msg := <-ch // 一直阻塞,直到接收到通道消息
    println(msg)
}

// $ go run main.go
// 输出如下
/**
  hello world
*/

死锁

package main

func main() {
    ch := make(chan string) // 没有设置通道的长度

    ch <- "hello world" // 向通道发送数据,但是没有接收者

    msg := <-ch // 代码执行不到这里, 因为上面阻塞发送数据时,就已经死锁了
    println(msg)
}

// $ go run main.go
// 输出如下
/**
  fatal error: all goroutines are asleep - deadlock!

  ...
  ...

  exit status 2
*/

非阻塞通道

图片来源: https://stackoverflow.com/questions/39826692/what-are-channels-used-for

例子

ch := make(chan string, 10) // 缓冲通道, 容量为 10

3 种操作

发送

  • • 如果通道已满 (元素数量达到容量), 发送操作将会阻塞,直到另一个 goroutine 在对应的通道上面完成接收操作, 两个 goroutine 才可以继续执行

  • • 如果通道未满,发送操作不会阻塞

语法规则

通道变量 <- 数据

# 例如: 将变量 x 发送到通道 ch
ch <- x 

接收

  • • 如果通道已空 (元素数量为 0),接收操作将会阻塞,直到另一个 goroutine 在对应的通道上面完成发送操作, 两个 goroutine 才可以继续执行

  • • 如果通道不为空,接收操作不会阻塞

语法规则

<- 通道变量

# 例如: 从通道 ch 接收一个值,并且丢弃
<-ch 
接收变量 <- 通道变量

# 例如: 从通道 ch 接收一个值,并且赋值给变量 x
x := <-ch 

关闭

详情见 关闭通道

例子

缓存通道容量为 2

package main

func main() {
    ch := make(chan string, 2)

    ch <- "hello" // 不会死锁,因为 ch 是缓冲通道
    ch <- "world"

    println(<-ch)
    println(<-ch)
}

// $ go run main.go
// 输出如下
/**
  hello 
  world
*/

扩展阅读

====

  1. 1. 死锁 - 维基百科

联系我

有关Go 快速入门指南 - 缓冲通道和非缓冲通道的更多相关文章

  1. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  2. 微信小程序开发入门与实战(Behaviors使用) - 2

    @作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors    1、什么是behaviors    2、behaviors的工作方式    3、创建behavior    4、导入并使用behavior    5、behavior中所有可用的节点    6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors    1、什么是behaviorsbehaviors是小程序中,用于实现

  3. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  4. ES基础入门 - 2

    ES一、简介1、ElasticStackES技术栈:ElasticSearch:存数据+搜索;QL;Kibana:Web可视化平台,分析。LogStash:日志收集,Log4j:产生日志;log.info(xxx)。。。。使用场景:metrics:指标监控…2、基本概念Index(索引)动词:保存(插入)名词:类似MySQL数据库,给数据Type(类型)已废弃,以前类似MySQL的表现在用索引对数据分类Document(文档)真正要保存的一个JSON数据{name:"tcx"}二、入门实战{"name":"DESKTOP-1TSVGKG","cluster_name":"elasticsear

  5. ruby - 如何以表格格式快速打印 Ruby 哈希值? - 2

    有没有办法快速将表格格式的ruby​​哈希打印到文件中?如:keyAkeyBkeyC...1232343451253474456...其中散列的值是不同大小的数组。还是使用双循环是唯一的方法?谢谢 最佳答案 试试我写的这个gem(在表中打印散列、ruby对象、ActiveRecord对象):http://github.com/arches/table_print 关于ruby-如何以表格格式快速打印Ruby哈希值?,我们在StackOverflow上找到一个类似的问题:

  6. Ruby 和指南针路径与 yeoman 项目 - 2

    我安装了ruby​​、yeoman,当我运行我的项目时,出现了这个错误:Warning:Running"compass:dist"(compass)taskWarning:YouneedtohaveRubyandCompassinstalledthistasktowork.Moreinfo:https://github.com/gruUse--forcetocontinue.Use--forcetocontinue.我有进入可变session目标的路径,但它不起作用。谁能帮帮我? 最佳答案 我必须运行这个:geminstallcom

  7. ruby-on-rails - Textmate 'Go to symbol' 相当于 Vim - 2

    在Railcasts上,我注意到一个非常有趣的功能“转到符号”窗口。它像Command-T一样工作,但显示当前文件中可用的类和方法。如何在vim中获取它? 最佳答案 尝试:helptags有各种程序和脚本可以生成标记文件。此外,标记文件格式非常简单,因此很容易将sed(1)或类似的脚本组合在一起,无论您使用何种语言,它们都可以生成标记文件。轻松获取标记文件(除了下载生成器之外)的关键在于格式化样式而不是实际解析语法。 关于ruby-on-rails-Textmate'Gotosymbol

  8. 电脑启动后显示器黑屏怎么办?排查下面4个问题,快速解决 - 2

    电脑启动出现显示器黑屏是一个相当常见的问题。如果您遇到了这个问题,不要惊慌,因为它有很多可能的原因,可以采取一些简单的措施来解决它。在本文中,小编将介绍下面4种常见的电脑启动后显示器黑屏的原因,排查这些原因,快速解决! 演示机型:联想Ideapad700-15ISK-ISE系统版本:Windows10一、显示器问题如果出现电脑启动后显示器黑屏的情况。那么首先您需要检查一下显示器是否正常工作。您可以通过更换另一个显示器或将当前显示器连接到另一台计算机来检查显示器是否存在问题。如果问题仍然存在,那么您可以排除显示器故障的可能性。 二、显卡问题如果您的电脑配备了独立显卡,那么显卡故障也可能是导致电脑

  9. 区块链入门教程(6)--WeBASE-Front节点前置服务安装 - 2

    文章目录1.任务背景2.任务目标3.相关知识点4.任务实操4.1安装配置JDK4.2启动FISCOBCOS4.3下载解压WeBASE-Front4.4拷贝sdk证书文件4.5启动节点4.6访问节点4.7检查运行状态5.任务总结1.任务背景FISCOBCOS其实是有控制台管理工具,用来对区块链系统进行各种管理操作。但是对于初学者来说,还是可视化界面更友好,本节就来介绍WeBASE管理平台,这是一款微众银行开源的自研区块链中间件平台,可以降低区块链使用的门槛,大幅提高区块链应用的开发效率。微众银行是腾讯牵头设立的民营银行,在国内民营银行里还是比较出名的。微众银行参与FISCOBCOS生态建设,一定

  10. Tcl脚本入门笔记详解(一) - 2

    TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是

随机推荐