当前位置: 首页 > news >正文

Go并发可视化解释 - Select语句

昨天,我发布了一篇文章,用可视化的方式解释了Golang中通道(Channel)的工作原理。如果你对通道的理解仍然存在困难,最好呢请在阅读本文之前先查看那篇文章。作为一个快速的复习:Partier、Candier 和 Stringer 经营着一家咖啡店。Partier 协助从顾客接收订单,然后将这些订单传递给厨房,Candier 和 Stringer 制作咖啡。

49892cf1f41bacfb46d4aadadf9b88b0.png
1*SuZghSKVBqKMuv7E25hWPw.png

Gophers 咖啡馆

在本文中,我将以视觉方式解释 select 语句,这是另一个在Go应用程序中处理并发的强大工具。Gophers 和他们的想象中的咖啡馆仍然会是我的伙伴,但这次,让我们聚焦在 Partier 和订单部分。

场景

Gophers 咖啡馆意识到越来越多的顾客想通过食品外卖应用订购咖啡。因此,除了现场点餐外,他们还选择了一款食品外卖应用。Partier 同时监听来自这两个通道的订单,并将这些订单通过另一个通道 queue 转发给 Candier 和 Stringer。

select {
case order := <-appOrders:queue <- order
case order := <-inShopOrders:queue <- order
}

当任何一个通道接收到订单时,Partier 会将其转发到 queue 通道。

a30643d7faa8caec4ff3c0f2a954ba0e.png
bb2c1d6a145925553262093510ac42d5.png

如果两个通道都有订单,其中之一将被选择。在真实的咖啡馆中,来自 inShopOrders 的订单可能会被优先处理。然而,在Go应用程序中,我们不能保证会选择哪个订单。还请注意,select 语句的每次执行只会选取一个订单,Partier 不会先选择一个订单,然后再选择另一个订单。尽管如此,在许多应用程序中,select 语句通常在 for 循环内部,使得前一次迭代中留下的订单在下一次迭代中有机会被选取。

for {select {case order := <-appOrders:queue <- ordercase order := <-inShopOrders:queue <- order}
}

但是,如果两个通道都有订单,它们将再次进行公平竞争。

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)
}

感谢您一直阅读到文章末尾。请考虑关注下作者啦~

相关文章:

Go并发可视化解释 - Select语句

昨天&#xff0c;我发布了一篇文章&#xff0c;用可视化的方式解释了Golang中通道&#xff08;Channel&#xff09;的工作原理。如果你对通道的理解仍然存在困难&#xff0c;最好呢请在阅读本文之前先查看那篇文章。作为一个快速的复习&#xff1a;Partier、Candier 和 Stringe…...

在线SM4(国密)加密解密工具

在线SM4(国密)加密解密工具...

golang的类型断言语法

例子1 在 Go 中&#xff0c;err.(interface{ Timeout() bool }) 是一个类型断言语法。它用于检查一个接口类型的变量 err 是否实现了一个带有 Timeout() bool 方法的接口。 具体而言&#xff0c;该类型断言的语法如下&#xff1a; if v, ok : err.(interface{ Timeout() boo…...

提速换挡 | 至真科技用技术打破业务壁垒,助力出海破局增长

各个行业都在谈出海&#xff0c;但真正成功的又有多少&#xff1f; 李宁出海十年海外业务收入占比仅有1.3%&#xff0c;走出去战略基本失败。 京东出海业务磕磕绊绊&#xff0c;九年过去国际化业务至今在财报上都不配拥有姓名。 几百万砸出去买量&#xff0c;一点水花都没有…...

第3篇:vscode搭建esp32 arduino开发环境

第1篇:Arduino与ESP32开发板的安装方法 第2篇:ESP32 helloword第一个程序示范点亮板载LED 1.下载vscode并安装 https://code.visualstudio.com/ 运行VSCodeUserSetup-x64-1.80.1.exe 2.点击扩展&#xff0c;搜索arduino,并点击安装 3.点击扩展设置&#xff0c;配置arduino…...

Apache Shiro是什么

特点 Apache Shiro是一个强大且易用的Java安全框架,用于身份验证、授权、会话管理和加密。它的设计目标是简化应用程序的安全性实现,使开发人员能够更轻松地处理各种安全性问题,从而提高应用程序的安全性和可维护性。下面是一些Apache Shiro的关键特点和概念: 特点和概念…...

Socket基本原理

一、简单介绍 Socket&#xff0c;又称套接字&#xff0c;是Linux跨进程通信&#xff08;IPC&#xff0c;Inter Process Communication&#xff09;方式的一种。相比于其他IPC方式&#xff0c;Socket牛逼在于可做到同一台主机内跨进程通信&#xff0c;不同主机间的跨进程通信。…...

Docker容器:本地私有仓库、harbor私有仓库部署与管理

文章目录 Docker容器&#xff1a;本地私有仓库、harbor私有仓库部署与管理一.本地私有仓库1.本地私有仓库概述2.搭建本地私有仓库3.容器重启策略简介 二.harbor私有仓库部署与管理1.什么是harbor2.Harbor的特性3、Harbor的构成4.Harbor私有仓库架构及数据流向5.harbor部署及配置…...

Mobx在非react组件中修改数据,在ts/js中修改数据实现响应式更新

我们都之前在封装mobx作为数据存储的时候&#xff0c;使用到了useContext作为包裹&#xff0c;将store变成了一个hooks使用&#xff0c;封装代码: import React from react import UserInfo from ./user import Setting from ./seting import NoteStore from ./noteclass Stor…...

什么是异步编程?什么是回调地狱(callback hell)以及如何避免它?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 异步编程⭐ 回调地狱&#xff08;Callback Hell&#xff09;⭐ 如何避免回调地狱1. 使用Promise2. 使用async/await3. 模块化和分离 ⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订…...

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…...

【Linux】多线程概念线程控制

文章目录 多线程概念Linux下进程和线程的关系pid本质上是轻量级进程id&#xff0c;换句话说&#xff0c;就是线程IDLinux内核是如何创建一个线程的线程的共享和独有线程的优缺点 线程控制POSIX线程库线程创建线程终止线程等待线程分离 多线程概念 Linux下进程和线程的关系 在…...

Qt --- 自定义提示框 类似QMessagebox

QMessageBox::information(NULL, QString("title"), QString("I am information")); 以下是自定义提示框的代码&#xff0c;有图有真相&#xff01;提示框大部分都采用模态的形式&#xff0c;关于模态也不再多提&#xff01;所以父类为QDialog&#xff0c;…...

Redis 分布式锁与 Redlock 算法实现

Redis 分布式锁与 Redlock 算法实现 一、简介1. Redis的分布式锁2. 分布式锁的实现原理 二、Redis 分布式锁使用场景1. 分布式系统中数据资源的互斥访问2. 分布式环境中多个节点之间的协作3. 常见场景及应用 三、Redlock算法的原理与实现1. Redlock算法的背景2. Redlock算法的原…...

【附安装包】Inventor2024安装教程 机械制图|三维制图

软件下载 软件&#xff1a;Inventor版本&#xff1a;2024语言&#xff1a;简体中文大小&#xff1a;5.61G安装环境&#xff1a;Win11/Win10/Win8/Win7硬件要求&#xff1a;CPU2.5GHz 内存8G(或更高&#xff09;下载通道①百度网盘丨64位下载链接&#xff1a;https://pan.baidu…...

c++ 判断基类指针指向的真实对象类型

在 c 面向对象使用中&#xff0c;我们常常会定义一个基类类型的指针&#xff0c;在运行过程中&#xff0c;这个指针可能指向一个基类类型的对象&#xff0c;也可能指向的是其子类类型的对象&#xff0c;那现在问题来了&#xff0c;我们如何去判断这个指针到底执行了一个什么类型…...

退出屏保前玩一把游戏吧!webBrowser中网页如何调用.NET方法

本文主要以 HackerScreenSaver 新功能的开发经历介绍 webBrowser中网页如何调用.NET方法的过程。 1. 背景 之前开源了一款名为 HackerScreenSaver 的 Windows 屏保程序。该程序具有模拟黑客炫酷界面的特点&#xff0c;用户可以将自定义的网页作为锁屏界面。不久前&#xff0c;…...

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...

【网络】IP网络层和数据链路层

IP协议详解 1.概念 1.1 四层模型 应用层&#xff1a;解决如何传输数据&#xff08;依照什么格式/协议处理数据&#xff09;的问题传输层&#xff1a;解决可靠性问题网络层&#xff1a;数据往哪里传&#xff0c;怎么找到目标主机数据链路层&#xff08;物理层&#xff09;&…...

基于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.…...

mysql57、mysql80 目录结构 之 Windows

查看mysql 数据存储的位置 /bin&#xff1a;存储可执行文件&#xff0c;主要包含客户端和服务端启动程序&#xff0c;如mysql.exe、mysqld.exe等 /docs&#xff1a;存放一些文档 /include&#xff1a;用于放置一些头文件&#xff0c;如&#xff1a;mysql.h、mysqld_error.h 等 …...

Mac操作系统Safari 17全新升级:秋季推出全部特性

苹果的内置浏览器可能是Mac上最常用的应用程序&#xff08;是的&#xff0c;甚至比Finder、超级Mac Geeks还要多&#xff09;。因此&#xff0c;苹果总是为其浏览器Safari添加有用的新功能。在今年秋天与macOS Sonoma一起推出的第17版中&#xff0c;Safari可以帮助你提高工作效…...

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);- 参数&#xff1a;- sockfd : 通信的fd- buf : 要发送的数据- len : 发送数据的长度…...

ChatGPT提示与技巧分享:如何作出更好的提示2023年8月

​对ChatGPT的一些酷炫技巧感兴趣吗?这里提供了一些可以帮助你充分利用ChatGPT&#xff0c;成为AI工具专家的技巧。 毫无疑问&#xff0c;ChatGPT是目前最广泛使用的人工智能工具之一。它不仅毫不留情地取代了一些特定领域常用的软件小工具&#xff08;如智能对联、经典语录生…...

网络安全(自学黑客)一文全解

目录 特别声明&#xff1a;&#xff08;文末附资料笔记工具&#xff09; 一、前言 二、定义 三、分类 1.白帽黑客&#xff08;White Hat Hacker&#xff09; 2.黑帽黑客&#xff08;Black Hat Hacker&#xff09; 3.灰帽黑客&#xff08;Gray Hat Hacker&#xff09; 四…...

Vue中ElementUI结合transform使用时,发现弹框定位不准确问题

在近期开发中&#xff0c;需要将1920*1080放到更大像素大屏上演示&#xff0c;所以需要使用到transform来对页面进行缩放&#xff0c;但是此时发现弹框定位出错问题&#xff0c;无法准备定位到实际位置。 查看element-ui官方文档无果后&#xff0c;打算更换新的框架进行开发&am…...

(一)连续随机量的生成-基于分布函数

连续随机量的生成-基于分布函数 1. 概率积分变换方法&#xff08;分布函数&#xff09;2. Python编程实现指数分布的采样 1. 概率积分变换方法&#xff08;分布函数&#xff09; Consider drawing a random quantity X X X from a continuous probability distribution with …...

【springboot】Spring Cache缓存:

文章目录 一、导入Maven依赖&#xff1a;二、实现思路&#xff1a;三、代码开发&#xff1a; 一、导入Maven依赖&#xff1a; <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId><…...

数学建模-建模算法(4)

python虽然不是完全为数学建模而生的&#xff0c;但是它完整的库让它越来越适合建模了。 - 线性规划&#xff1a;使用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…...

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…...

取消wordpress还原/seo同行网站

实现多操作系统计算机的资源共享.pdf2004年6月 电 脑 学 习 第3期实现多操作系统计算机的资源共享赵晓静 孙全尚可矧摘 要 阐述在一台多操作系统计算机上共享应用程序、IE资源以及Ou‰kExpress电子邮件的方法。多操作系统 资源共享 Windows98 Willdows2000IE Oudook关键词 Expr…...

求一个用脚做asmr的网站/厦门seo代理商

Instruments 是应用程序用来动态跟踪和分析 Mac OS X 和 iOS 代码的实用工具。 这是一个灵活而强大的工具,它让你可以跟踪一个或多个进程,并检查收集的数据。 这样,Instruments可以帮你更好的理解应用程序和操作系统的行为。 使用 Instruments 应用,你可以使用特殊的工具(即 in…...

wordpress会员中心vip收费/外贸建站网站推广

维密终于来中国了&#xff01;此前&#xff0c;维密秀历史上只有3次离开过美国本土&#xff0c;分别是法国戛纳、英国伦敦和法国巴黎&#xff0c;上海维密秀也是第一次移师亚洲。如果你还在为满屏的大长腿流口水&#xff0c;不知道主看哪个好&#xff0c;优达菌还是首推维密超模…...

html5 网站布局应用教程/怎么开网站平台

现在我们继续这个新闻客户端的开发&#xff0c;今天分享的是下拉刷新的实现&#xff0c;我们都知道下拉刷新是一个应用很常见也很实用的功能。我这个应用是通过拉ListView来实现刷新的&#xff0c;先看一张刷新的原理图 从图中可知&#xff0c;手指移动的距离就是dy。 刷新分…...

兰州做网站/青岛谷歌优化

2015-01-06在cass9.0中如何标高程1。使用南方cass软件“工程应用”菜单下的“等高线生成数据文件”命令&#xff0c;提取原始地形等高线上的坐标和高程数据&#xff0c;保存为原始地形数据。dat 文件。2。将各点设计平均高程也保存为cass格式的坐标高程数据文件&#xff0c;保存…...

网站优化怎样做/深圳做网站的公司有哪些

你肯定经历过这样的时刻&#xff0c;看着电脑屏幕抓着头&#xff0c;困惑着&#xff1a;「为什么我会在代码中使用这三个术语&#xff0c;它们有什么区别吗&#xff1f;」因为它们看起来实在太相似了。为了理解这些术语有什么不同&#xff0c;你需要了解一些关于机器学习的术语…...