Go并发可视化解释 - Select语句
昨天,我发布了一篇文章,用可视化的方式解释了Golang中通道(Channel)的工作原理。如果你对通道的理解仍然存在困难,最好呢请在阅读本文之前先查看那篇文章。作为一个快速的复习:Partier、Candier 和 Stringer 经营着一家咖啡店。Partier 协助从顾客接收订单,然后将这些订单传递给厨房,Candier 和 Stringer 制作咖啡。
![null 49892cf1f41bacfb46d4aadadf9b88b0.png](https://img-blog.csdnimg.cn/img_convert/49892cf1f41bacfb46d4aadadf9b88b0.png)
Gophers 咖啡馆
在本文中,我将以视觉方式解释 select
语句,这是另一个在Go应用程序中处理并发的强大工具。Gophers 和他们的想象中的咖啡馆仍然会是我的伙伴,但这次,让我们聚焦在 Partier 和订单部分。
场景
Gophers 咖啡馆意识到越来越多的顾客想通过食品外卖应用订购咖啡。因此,除了现场点餐外,他们还选择了一款食品外卖应用。Partier 同时监听来自这两个通道的订单,并将这些订单通过另一个通道 queue
转发给 Candier 和 Stringer。
select {
case order := <-appOrders:queue <- order
case order := <-inShopOrders:queue <- order
}
当任何一个通道接收到订单时,Partier 会将其转发到 queue
通道。
![null a30643d7faa8caec4ff3c0f2a954ba0e.png](https://img-blog.csdnimg.cn/img_convert/a30643d7faa8caec4ff3c0f2a954ba0e.png)
![null bb2c1d6a145925553262093510ac42d5.png](https://img-blog.csdnimg.cn/img_convert/bb2c1d6a145925553262093510ac42d5.png)
如果两个通道都有订单,其中之一将被选择。在真实的咖啡馆中,来自 inShopOrders
的订单可能会被优先处理。然而,在Go应用程序中,我们不能保证会选择哪个订单。还请注意,select
语句的每次执行只会选取一个订单,Partier 不会先选择一个订单,然后再选择另一个订单。尽管如此,在许多应用程序中,select
语句通常在 for
循环内部,使得前一次迭代中留下的订单在下一次迭代中有机会被选取。
for {select {case order := <-appOrders:queue <- ordercase order := <-inShopOrders:queue <- order}
}
但是,如果两个通道都有订单,它们将再次进行公平竞争。
![null 04875e5751783e5afef1dfaec1df8735.png](https://img-blog.csdnimg.cn/img_convert/04875e5751783e5afef1dfaec1df8735.png)
默认分支
在非高峰时段,订单不多,Partier 在等待上花费了大量时间。他认为,通过做其他事情,例如清洁桌子,他可以更有成效地利用时间。这可以通过 default
实现。
for {select {case order := <-appOrders:log.Println("There is an order coming from appOrders channel")queue <- ordercase order := <-inShopOrders:log.Println("There is an order coming from inShopOrders channel")queue <- orderdefault:log.Println("There is no order on both channels, I will do cleaning instead")doCleaning()}
}
time.After()
通常,time.After(duration)
与 select
一起使用,以防止永远等待。与 default
立即在没有可用通道时执行不同,time.After(duration)
创建一个普通的 <-chan Time
,等待 duration
过去,然后在返回的通道上发送当前时间。这个通道在 select
语句中与其他通道一样被处理。正如你所看到的,select
语句中的通道可以是不同类型的。
shouldClose := false
closeHourCh := time.After(8 * time.Hour)for !shouldClose {select {case order := <-appOrders:log.Println("There is an order coming from appOrders channel")queue <- ordercase order := <-inShopOrders:log.Println("There is an order coming from inShopOrders channel")queue <- ordercase now := <-closeHourCh:log.Printf("It is %v now, the shop is closing\n", now)shouldClose = truedefault:log.Println("There is no order on both channels, I will go cleaning instead")doCleaning()}
}log.Println("Shop is closed, I'm going home now. Bye!")
在处理远程API调用时,这种技术非常常见,因为我们不能保证远程服务器何时返回或是否返回。有了 context
,我们通常不需要这样做。
responseChannel := make(chan interface{})
timer := time.NewTimer(timeout)select {
case resp := <-responseChannel:log.Println("Processing response")processResponse(resp)timer.Stop()
case <-timer.C:log.Println("Time out, giving up")
}
示例代码
让我们以一个完整的虚构咖啡馆代码结束本文。这里还有一件需要注意的事情,从关闭的通道中选择将总是立即返回。因此,如果您认为有必要,使用“comma ok”习惯用法。亲自动手编码是学习编程的最佳方式。因此,如果您对 select
不太熟悉,我建议您在IDE上复制并尝试修改此代码。
祝您编码愉快!
package mainimport ("fmt""log""time"
)func main() {appOrders := make(chan order, 3)inShopOrders := make(chan order, 3)queue := make(chan order, 3)go func() {for i := 0; i < 6; i++ {appOrders <- order(100 + i)time.Sleep(10 * time.Second)}close(appOrders)}()go func() {for i := 0; i < 4; i++ {inShopOrders <- order(200 + i)time.Sleep(15 * time.Second)}close(inShopOrders)}()go partier(appOrders, inShopOrders, queue)for o := range queue {log.Printf("Served %s\n", o)}log.Println("Done!")
}func partier(appOrders <-chan order, inShopOrders <-chan order, queue chan<- order) {shouldClose := falsecloseTimeCh := time.After(1 * time.Minute)for !shouldClose {select {case ord, ok := <-appOrders:if ok {log.Printf("There is %s coming from appOrders channel\n", ord)queue <- ord}case ord, ok := <-inShopOrders:if ok {log.Printf("There is %s coming from inShopOrders channel\n", ord)queue <- ord}case now := <-closeTimeCh:log.Printf("It is %v now, the shop is closing\n", now)shouldClose = truedefault:log.Println("There is no order on both channels, I will go cleaning instead")doCleaning()}}close(queue)log.Println("Shop is closed, I'm going home now. Bye!")
}func doCleaning() {time.Sleep(5 * time.Second)log.Println("Partier: Cleaning done")
}type order intfunc (o order) String() string {return fmt.Sprintf("order-%02d", o)
}
感谢您一直阅读到文章末尾。请考虑关注下作者啦~
相关文章:
![](https://img-blog.csdnimg.cn/img_convert/04875e5751783e5afef1dfaec1df8735.png)
Go并发可视化解释 - Select语句
昨天,我发布了一篇文章,用可视化的方式解释了Golang中通道(Channel)的工作原理。如果你对通道的理解仍然存在困难,最好呢请在阅读本文之前先查看那篇文章。作为一个快速的复习:Partier、Candier 和 Stringe…...
![](https://img-blog.csdnimg.cn/f0b1e58fcf1246cc91ffb7f6c0887982.png)
在线SM4(国密)加密解密工具
在线SM4(国密)加密解密工具...
![](https://www.ngui.cc/images/no-images.jpg)
golang的类型断言语法
例子1 在 Go 中,err.(interface{ Timeout() bool }) 是一个类型断言语法。它用于检查一个接口类型的变量 err 是否实现了一个带有 Timeout() bool 方法的接口。 具体而言,该类型断言的语法如下: if v, ok : err.(interface{ Timeout() boo…...
![](https://img-blog.csdnimg.cn/img_convert/583e7f4048be315f9b4b86ec6dd8f5f3.png)
提速换挡 | 至真科技用技术打破业务壁垒,助力出海破局增长
各个行业都在谈出海,但真正成功的又有多少? 李宁出海十年海外业务收入占比仅有1.3%,走出去战略基本失败。 京东出海业务磕磕绊绊,九年过去国际化业务至今在财报上都不配拥有姓名。 几百万砸出去买量,一点水花都没有…...
![](https://img-blog.csdnimg.cn/37ac1ce21e574f5aa535299429ab867c.jpeg)
第3篇:vscode搭建esp32 arduino开发环境
第1篇:Arduino与ESP32开发板的安装方法 第2篇:ESP32 helloword第一个程序示范点亮板载LED 1.下载vscode并安装 https://code.visualstudio.com/ 运行VSCodeUserSetup-x64-1.80.1.exe 2.点击扩展,搜索arduino,并点击安装 3.点击扩展设置,配置arduino…...
![](https://www.ngui.cc/images/no-images.jpg)
Apache Shiro是什么
特点 Apache Shiro是一个强大且易用的Java安全框架,用于身份验证、授权、会话管理和加密。它的设计目标是简化应用程序的安全性实现,使开发人员能够更轻松地处理各种安全性问题,从而提高应用程序的安全性和可维护性。下面是一些Apache Shiro的关键特点和概念: 特点和概念…...
![](https://img-blog.csdnimg.cn/b094347271f944629ceab31a2892d9ee.png)
Socket基本原理
一、简单介绍 Socket,又称套接字,是Linux跨进程通信(IPC,Inter Process Communication)方式的一种。相比于其他IPC方式,Socket牛逼在于可做到同一台主机内跨进程通信,不同主机间的跨进程通信。…...
![](https://img-blog.csdnimg.cn/50606a5efe314a9fbd58b609529c2300.png)
Docker容器:本地私有仓库、harbor私有仓库部署与管理
文章目录 Docker容器:本地私有仓库、harbor私有仓库部署与管理一.本地私有仓库1.本地私有仓库概述2.搭建本地私有仓库3.容器重启策略简介 二.harbor私有仓库部署与管理1.什么是harbor2.Harbor的特性3、Harbor的构成4.Harbor私有仓库架构及数据流向5.harbor部署及配置…...
![](https://img-blog.csdnimg.cn/eaf20b2fbf954dabb1ebb38f125541d6.png)
Mobx在非react组件中修改数据,在ts/js中修改数据实现响应式更新
我们都之前在封装mobx作为数据存储的时候,使用到了useContext作为包裹,将store变成了一个hooks使用,封装代码: import React from react import UserInfo from ./user import Setting from ./seting import NoteStore from ./noteclass Stor…...
![](https://img-blog.csdnimg.cn/49003d19702f43c9a233b53cf361faf0.png)
什么是异步编程?什么是回调地狱(callback hell)以及如何避免它?
聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 异步编程⭐ 回调地狱(Callback Hell)⭐ 如何避免回调地狱1. 使用Promise2. 使用async/await3. 模块化和分离 ⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订…...
![](https://www.ngui.cc/images/no-images.jpg)
Java8 Stream流常见操作--持续更新中
创建新数组 List<Fruit> newList fruits.stream().map(f -> new Fruit(f.getId(), f.getName() "s", f.getCountry())).collect(Collectors.toList())筛选数组 Map<Boolean, List<TransferData>> preAvg list.stream().collect(Collectors…...
![](https://img-blog.csdnimg.cn/419eb27c2aba441d9fa2ac9565374314.png)
【Linux】多线程概念线程控制
文章目录 多线程概念Linux下进程和线程的关系pid本质上是轻量级进程id,换句话说,就是线程IDLinux内核是如何创建一个线程的线程的共享和独有线程的优缺点 线程控制POSIX线程库线程创建线程终止线程等待线程分离 多线程概念 Linux下进程和线程的关系 在…...
![](https://img-blog.csdnimg.cn/64a0814c73a742839a6488d909ac0232.png)
Qt --- 自定义提示框 类似QMessagebox
QMessageBox::information(NULL, QString("title"), QString("I am information")); 以下是自定义提示框的代码,有图有真相!提示框大部分都采用模态的形式,关于模态也不再多提!所以父类为QDialog,…...
![](https://www.ngui.cc/images/no-images.jpg)
Redis 分布式锁与 Redlock 算法实现
Redis 分布式锁与 Redlock 算法实现 一、简介1. Redis的分布式锁2. 分布式锁的实现原理 二、Redis 分布式锁使用场景1. 分布式系统中数据资源的互斥访问2. 分布式环境中多个节点之间的协作3. 常见场景及应用 三、Redlock算法的原理与实现1. Redlock算法的背景2. Redlock算法的原…...
![](https://hnxx.oss-cn-shanghai.aliyuncs.com/official/1689929181288.gif)
【附安装包】Inventor2024安装教程 机械制图|三维制图
软件下载 软件:Inventor版本:2024语言:简体中文大小:5.61G安装环境:Win11/Win10/Win8/Win7硬件要求:CPU2.5GHz 内存8G(或更高)下载通道①百度网盘丨64位下载链接:https://pan.baidu…...
![](https://img-blog.csdnimg.cn/ec40950a410e4f38b285c977c74abb22.png)
c++ 判断基类指针指向的真实对象类型
在 c 面向对象使用中,我们常常会定义一个基类类型的指针,在运行过程中,这个指针可能指向一个基类类型的对象,也可能指向的是其子类类型的对象,那现在问题来了,我们如何去判断这个指针到底执行了一个什么类型…...
![](https://img-blog.csdnimg.cn/b4ccae1f71bf48588721d6b20707938e.png)
退出屏保前玩一把游戏吧!webBrowser中网页如何调用.NET方法
本文主要以 HackerScreenSaver 新功能的开发经历介绍 webBrowser中网页如何调用.NET方法的过程。 1. 背景 之前开源了一款名为 HackerScreenSaver 的 Windows 屏保程序。该程序具有模拟黑客炫酷界面的特点,用户可以将自定义的网页作为锁屏界面。不久前,…...
![](https://img-blog.csdnimg.cn/af4574bf6ab840bf9c984a8519756202.png)
hive-列转行
转成 select customer_code,product_type from temp.temp_xx LATERAL VIEW explode(SPLIT(product_types,,)) table_tmp AS product_type where customer_code K100515182...
![](https://img-blog.csdnimg.cn/img_convert/5a073c882a765c45239db576a0d69b64.png)
【网络】IP网络层和数据链路层
IP协议详解 1.概念 1.1 四层模型 应用层:解决如何传输数据(依照什么格式/协议处理数据)的问题传输层:解决可靠性问题网络层:数据往哪里传,怎么找到目标主机数据链路层(物理层)&…...
![](https://img-blog.csdnimg.cn/3c75ef2f630c410d8cbae05dc1b505e6.jpeg#pic_center)
基于Spring Gateway路由判断器实现各种灰度发布场景
文章目录 1、灰度发布实现1.1 按随机用户的流量百分比实现灰度1.2 按人群划分实现的灰度1.2.1 通过Header信息实现灰度1.2.2 通过Query信息实现灰度1.2.3 通过RemoteAdd判断来源IP实现灰度 2、路由判断器2.1. After2.2. Before2.3. Between2.4. Cookie2.5. Header2.6. Host2.7.…...
![](https://img-blog.csdnimg.cn/9ab93278ac0c4745bb74c720e10b9e24.png)
mysql57、mysql80 目录结构 之 Windows
查看mysql 数据存储的位置 /bin:存储可执行文件,主要包含客户端和服务端启动程序,如mysql.exe、mysqld.exe等 /docs:存放一些文档 /include:用于放置一些头文件,如:mysql.h、mysqld_error.h 等 …...
![](https://img-blog.csdnimg.cn/img_convert/117d704517c4ad035d9213a3a24becab.png)
Mac操作系统Safari 17全新升级:秋季推出全部特性
苹果的内置浏览器可能是Mac上最常用的应用程序(是的,甚至比Finder、超级Mac Geeks还要多)。因此,苹果总是为其浏览器Safari添加有用的新功能。在今年秋天与macOS Sonoma一起推出的第17版中,Safari可以帮助你提高工作效…...
![](https://img-blog.csdnimg.cn/41c71f33efac479a90ed3bcfac336e77.png)
UDP通信、本地套接字
#include <sys/types.h> #include <sys/socket > ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);- 参数:- sockfd : 通信的fd- buf : 要发送的数据- len : 发送数据的长度…...
![](https://img-blog.csdnimg.cn/img_convert/d205de4d8be837d1ab37cb739a023891.jpeg)
ChatGPT提示与技巧分享:如何作出更好的提示2023年8月
对ChatGPT的一些酷炫技巧感兴趣吗?这里提供了一些可以帮助你充分利用ChatGPT,成为AI工具专家的技巧。 毫无疑问,ChatGPT是目前最广泛使用的人工智能工具之一。它不仅毫不留情地取代了一些特定领域常用的软件小工具(如智能对联、经典语录生…...
![](https://img-blog.csdnimg.cn/88b6d127f6f644c8a7cfc06047c32dba.png)
网络安全(自学黑客)一文全解
目录 特别声明:(文末附资料笔记工具) 一、前言 二、定义 三、分类 1.白帽黑客(White Hat Hacker) 2.黑帽黑客(Black Hat Hacker) 3.灰帽黑客(Gray Hat Hacker) 四…...
![](https://img-blog.csdnimg.cn/a291947ee8234853ae170f8fd3cb9d62.png)
Vue中ElementUI结合transform使用时,发现弹框定位不准确问题
在近期开发中,需要将1920*1080放到更大像素大屏上演示,所以需要使用到transform来对页面进行缩放,但是此时发现弹框定位出错问题,无法准备定位到实际位置。 查看element-ui官方文档无果后,打算更换新的框架进行开发&am…...
![](https://www.ngui.cc/images/no-images.jpg)
(一)连续随机量的生成-基于分布函数
连续随机量的生成-基于分布函数 1. 概率积分变换方法(分布函数)2. Python编程实现指数分布的采样 1. 概率积分变换方法(分布函数) Consider drawing a random quantity X X X from a continuous probability distribution with …...
![](https://img-blog.csdnimg.cn/08fddb11ac51453d93d5a8935bad8965.png)
【springboot】Spring Cache缓存:
文章目录 一、导入Maven依赖:二、实现思路:三、代码开发: 一、导入Maven依赖: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId><…...
![](https://www.ngui.cc/images/no-images.jpg)
数学建模-建模算法(4)
python虽然不是完全为数学建模而生的,但是它完整的库让它越来越适合建模了。 - 线性规划:使用scipy.optimize.linprog()函数 python from scipy.optimize import linprogc [-1, 4] A [[-3, 1], [1, 2]] b [6, 4] x0_bounds (None, None) x1_bound…...
![](https://www.ngui.cc/images/no-images.jpg)
python之函数返回数据框
1.原始文件 ##gff-version 3 Chr1A IWGSC_v2.1 gene 40098 70338 33 - . IDTraesCS1A03G0000200;previous_idTraesCS1A02G000100;primconfHC;NameTraesCS1A03G0000200;cdsCDS_OK;mappingfullMatchWithMissmatches Chr1A IWGSC_v2.1 mRN…...
![](/images/no-images.jpg)
取消wordpress还原/seo同行网站
实现多操作系统计算机的资源共享.pdf2004年6月 电 脑 学 习 第3期实现多操作系统计算机的资源共享赵晓静 孙全尚可矧摘 要 阐述在一台多操作系统计算机上共享应用程序、IE资源以及Ou‰kExpress电子邮件的方法。多操作系统 资源共享 Windows98 Willdows2000IE Oudook关键词 Expr…...
![](https://images2015.cnblogs.com/blog/501599/201508/501599-20150830213725609-1545905511.png)
求一个用脚做asmr的网站/厦门seo代理商
Instruments 是应用程序用来动态跟踪和分析 Mac OS X 和 iOS 代码的实用工具。 这是一个灵活而强大的工具,它让你可以跟踪一个或多个进程,并检查收集的数据。 这样,Instruments可以帮你更好的理解应用程序和操作系统的行为。 使用 Instruments 应用,你可以使用特殊的工具(即 in…...
![](/images/no-images.jpg)
wordpress会员中心vip收费/外贸建站网站推广
维密终于来中国了!此前,维密秀历史上只有3次离开过美国本土,分别是法国戛纳、英国伦敦和法国巴黎,上海维密秀也是第一次移师亚洲。如果你还在为满屏的大长腿流口水,不知道主看哪个好,优达菌还是首推维密超模…...
html5 网站布局应用教程/怎么开网站平台
现在我们继续这个新闻客户端的开发,今天分享的是下拉刷新的实现,我们都知道下拉刷新是一个应用很常见也很实用的功能。我这个应用是通过拉ListView来实现刷新的,先看一张刷新的原理图 从图中可知,手指移动的距离就是dy。 刷新分…...
![](https://img-blog.csdnimg.cn/img_convert/f37716c7e8733c0b7f704c0652d3b580.png)
兰州做网站/青岛谷歌优化
2015-01-06在cass9.0中如何标高程1。使用南方cass软件“工程应用”菜单下的“等高线生成数据文件”命令,提取原始地形等高线上的坐标和高程数据,保存为原始地形数据。dat 文件。2。将各点设计平均高程也保存为cass格式的坐标高程数据文件,保存…...
![](https://img-blog.csdnimg.cn/img_convert/552a6f3162a48438a155f247885d13ff.png)
网站优化怎样做/深圳做网站的公司有哪些
你肯定经历过这样的时刻,看着电脑屏幕抓着头,困惑着:「为什么我会在代码中使用这三个术语,它们有什么区别吗?」因为它们看起来实在太相似了。为了理解这些术语有什么不同,你需要了解一些关于机器学习的术语…...