Go语言学习编程实践:五种模式解决go中的并发问题

news2024/10/2 8:33:41

五种模式解决go中的并发问题

    • For-Select-Done
    • 扇入模式
    • 从流中获取前 n 个值
    • 订阅模式
    • 地图模式
    • 过滤模式

For-Select-Done

我们应该防止程序中发生任何泄露。所以我们应该对于留在程序中的go例程发送信号,让它知道它可以退出。
最常见的就是将for-select循环与通道结合起来,向go程序发送一个关闭信号。我们称它为“完成”通道。

func printIntegers(done <-chan struct{}, intStream <-chan int) {
	for{
		 select {
		 case i := <-intStream:
		 fmt.Println(i)
		 case <-done:
		 return
		 }
	 }
}

没有看懂,先记在这里……

扇入模式

在这里插入图片描述

func fanIn(ctx context.Context, fetchers ...<-chan interface{}) <-chan interface{} {
 combinedFetcher := make(chan interface{})
 // 1
 var wg sync.WaitGroup
 wg.Add(len(fetchers))
 
 // 2
 for _, f := range fetchers {
 f := f
 go func() {
 // 3
 
 defer wg.Done()
 for{
 select{
 case res := <-f:
 combinedFetcher <- res
 case <-ctx.Done():
 return
 }
 }
 }()
 }
 
 // 4
 // Channel cleanup
 go func() {
 wg.Wait()
 close(combinedFetcher)
 } ()
 return combinedFetcher
}

从流中获取前 n 个值

在这里插入图片描述

func takeFirstN(ctx context.Context, dataSource <-chan interface{}, n int) <-chan interface{} {
 // 1
 takeChannel := make(chan interface{})
 
 // 2
 go func() {
 defer close(takeChannel)
 // 3 
 for i := 0; i< n; i++ {
 select {
 case val, ok := <-dataSource:
 if !ok{
 return
 }
 takeChannel <- val
 case <-ctx.Done():
 return
 }
 }
 }()
 return takeChannel
}

订阅模式

type Subscription interface {
 Updates() <-chan Item
}
//On the other hand, we are going to use another interface as an abstraction to fetch the data we 
//need:
//另一方面,我们将使用另一个接口作为抽象来获取我们需要的数据。
type Fetcher interface {
 Fetch() (Item, error)
}
//For each of these we are going to have a concrete type implementing them.
//对于其中的每一个,我们都将有一个具体的类型来实现它们。
//For the subscription:
//对于订阅来说。
func NewSubscription(ctx context.Context, fetcher Fetcher, freq int) Subscription {
 s := &sub{
 fetcher: fetcher,
 updates: make(chan Item),
 }
// Running the Task Supposed to fetch our data
 go s.serve(ctx, freq)
 return s
}
type sub struct {
 fetcher Fetcher
 updates chan Item
}
func (s *sub) Updates() <-chan Item {
 return s.updates
}
//We are going to go into more details about what happens inside the serve method.
我们将更详细地介绍服务方法内部发生的事情。
//For the fetcher:
//对于取物者来说。
func NewFetcher(uri string) Fetcher {
 f := &fetcher{
 uri: uri,
 }
 return f
}
type fetcher struct {
 uri string
}
//Inside the serve method

//The serve method consists of a for-select-done type of loop:
//服务方法由一个 for-select-done 类型的循环组成。
func (s *sub) serve(ctx context.Context, checkFrequency int) {
 clock := time.NewTicker(time.Duration(checkFrequency) * time.Second)
 type fetchResult struct {
 fetched Item
 err error
 }
 fetchDone := make(chan fetchResult, 1)
 
 for {
 select {
 // Clock that triggers the fetch
 case <-clock.C:
 go func() {
fetched, err := s.fetcher.Fetch()
fetchDone <- fetchResult{fetched, err}
 }()
 // Case where the fetch result is
 // Ready to be consumed
 case result := <-fetchDone:
 fetched := result.fetched
 if result.err != nil {
 log.Println("Fetch error: %v \n Waiting the next iteration", result.err.Error())
break
 }
 s.updates <-fetched
 // Case where we need to close the server
 case <-ctx.Done():
 return
 }
 }
}

有一个修正,暂时先不提。

地图模式

func Map(done <-chan struct{}, inputStream <-chan int, operator func(int)int) <-chan int {
 // 1
 mappedStream := make(chan int)
 go func() {
 defer close(mappedStream)
 // 2
 for {
 select {
 case <-done:
 return
 // 3
 case i, ok := <-inputStream:
 if !ok { return }
 //4
 select {
 case <-done:
 return
 case mappedStream <- operator(i):
 }
 }
 }
 }()
 return mappedStream
func main() {
 done := make(chan struct{})
 defer close(done)
 
 // Generates a channel sending integers
 // From 0 to 9
 range10 := rangeChannel(done, 10)
 
 multiplierBy10 := func(x int) int {
 return x * 10
 }
 for num := range Map(done, range10, multiplierBy10) {
 fmt.Println(num)
 }
}

过滤模式

在这里插入图片描述

func Filter(done <-chan struct{}, inputStream <-chan int, operator func(int)bool) <-chan int {
 filteredStream := make(chan int)
 go func() {
 defer close(filteredStream)
 
 for {
 select {
 case <-done:
 return
 case i, ok := <-inputStream:
 if !ok {
 return
 }
 
 if !operator(i) { break }
 select {
 case <-done:
 return
 case filteredStream <- i:
 }
 }
 }
 }()
 return filteredStream
}
func main() {
 done := make(chan struct{})
 defer close(done)
 
 // Generates a channel sending integers
 // From 0 to 9
 range10 := rangeChannel(done, 10)
 
 isEven := func(x int) bool {
 return x % 2 == 0
 }
 for num := range Filter(done, range10, isEven) {
 fmt.Println(num)
 }
}

这五个模式是构建更大、更复杂的 Golang 应用程序的基石。这些解决方案可以解决你在处
理 GO 中的并发问题时可能遇到的问题。此外,你还可以在此基础上修改、扩展和创建新的
模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/397731.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UEFI启动流程

以上是UEFI系统运行的7个阶段&#xff0c;下边是详细描述&#xff1a; SEC阶段&#xff1a;&#xff08;安全验证&#xff09; 1、接收和处理系统的启动&#xff0c;重启&#xff0c;异常信号&#xff1b; 2、SEC阶段特色功能“Cache As RAM&#xff08;CAR&#xff09;”&am…

英伦四地到底是什么关系?

英格兰、苏格兰、威尔士和北爱尔兰四地到底是什么关系&#xff0c;为何苏格兰非要独立&#xff1f;故事还要从中世纪说起。大不列颠岛位于欧洲西部&#xff0c;和欧洲大陆隔海相望。在古代&#xff0c;大不列颠岛和爱尔兰属于凯尔特人的领地。凯尔特人是欧洲西部一个庞大的族群…

Caddy2学习笔记——Caddy2反向代理Frp内网穿透和反向代理PVE

一、环境概述 本人拥有一个国内云服务商的云主机和一个备案好的域名&#xff0c;通过caddy2来作为web服务器。 我的云主机是公网ip&#xff0c;地址为&#xff1a;43.126.100.78&#xff1b;我备案好的域名是&#xff1a;hotgirl.com 。后面的文章都以上述的ip和域名来进行讲解…

Actipro WinForms Studio Crack

Actipro WinForms Studio Crack 已验证Microsoft.NET 7兼容性。 添加了MetroDark配色方案。 添加了支持MetroLight和MetroDark颜色方案的MetroScrollBarRenderer。 添加了IWindowsColorScheme接口&#xff0c;该接口将替换对WindowsColorScheme的大多数引用。 添加了IWindowsCo…

Zookeeper客户端ZkClient、Curator的使用,史上最详细的教程来啦~

1 前言 本文主要介绍了操作Zookeeper的几种客户端的基础使用&#xff0c;希望对老铁们会有所帮助。 可以去操作zookeeper创建、删除、查询、修改znode节点 2 Zookeeper服务器客户端分类 目前&#xff0c;Zookeeper服务器有三种Java客户端&#xff1a; Zookeeper、Zkclient和…

inquirerjs

inquirerjs inquirerjs是一个用来实现命令行交互界面的工具集合。它帮助我们实现与用户的交互交流&#xff0c;比如给用户一个提醒&#xff0c;用户给我们一个答案&#xff0c;我们根据用户的答案来做一些事情&#xff0c;典型应用如plop等生成器工具。 npm install inquirer…

软测面试了一个00后,绝对能称为是内卷届的天花板

前言 公司前段缺人&#xff0c;也面了不少测试&#xff0c;结果竟然没有一个合适的。一开始瞄准的就是中级的水准&#xff0c;也没指望来大牛&#xff0c;提供的薪资也不低&#xff0c;面试的人很多&#xff0c;但平均水平很让人失望。令我印象最深的是一个00后测试员&#xf…

certum验证域名所有权

Certum证书支持 Email、文件上传、DNS解析 验证域名所有权。1 .Email 方式请确认自己域名已开通&#xff0c;域名邮箱。仅支持以下邮箱&#xff1a;adminyourdomain.comadministratoryourdomain.comwebmasteryourdomain.compostmasteryourdomain.comhostmasteryourdomain.com收…

深度学习笔记:卷积神经网络(1)

1 卷积神经网络整体结构 卷积神经网络&#xff08;CNN&#xff09;相比全连接网络多了卷积层和池化层。对于全连接网络&#xff0c;所有相邻层的神经元都用Affine层进行连接&#xff0c;如图中即为Affine-ReLU的连接组合。 卷积神经网络则包含卷积层和池化层与激活函数相连&a…

后端Java随机比大小游戏实战讲解

## - 利用print打印输出提示用户 ## - 利用Scanner函数抓取数据 ## - 利用Math方法实现随机数 #### 1.首先用到的是print函数&#xff0c;对用户进行提醒进一步的操作 通过System.out.print();提示用户进行选择买大买小。 #### 2.然后利用Scanner函数&#xff0c;对用户输出…

Spring Bean生命周期七大阶段-Java八股面试(七)

系列文章目录 第一章 ArrayList-Java八股面试(一) 第二章 HashMap-Java八股面试(二) 第三章 单例模式-Java八股面试(三) 第四章 线程池和Volatile关键字-Java八股面试(四) 第五章 ConcurrentHashMap-Java八股面试(五) 第六章 spring之refresh流程-Java八股面试(六) 提示&…

HTTPS是怎么加密数据的?

HTTPS是怎么加密数据的&#xff1f;对安全或密码学基础有了解的同学&#xff0c;应该知道常见的加密手段。一般来说&#xff0c;加密分为对称加密、非对称加密&#xff08;也叫公开密钥加密&#xff09;对称加密对称加密的意思就是&#xff0c;加密数据用的密钥&#xff0c;跟解…

儿童反复感染,是体质差还是免疫缺陷?

原发性免疫缺陷病&#xff08;PIDs&#xff09;它是一组由遗传因素或先天性免疫系统发育不良引起的免疫系统功能障碍综合征&#xff0c;可涉及固有免疫或适应性免疫。在中国&#xff0c;PID的中位发病率为6个月&#xff0c;男孩的发病率通常高于女孩。▼分类目前&#xff0c;国…

LearnOpenGL-光照-2.基础光照

本人刚学OpenGL不久且自学&#xff0c;文中定有代码、术语等错误&#xff0c;欢迎指正 我写的项目地址&#xff1a;https://github.com/liujianjie/LearnOpenGLProject 文章目录基础光照环境光照漫反射光照法向量计算漫反射光照最后一件事镜面光照基础光照 简介 现实世界的光照…

JavaEE初阶---初始进程

系统分配资源的最小单元--进程啥是进程看看进程操作系统如何管理进程PCB中的一些属性pid(进程id)内存指针文件描述符表进程调度并行和并发:进程调度的特性状态:优先级:记账信息:上下文:虚拟地址空间进程间交互我们日常使用计算机,大致可以抽象成如下形式:自上向下依次是 各种软…

易优cms switch 条件判断标签使用方法

【基础用法】 标签&#xff1a;switch 描述&#xff1a;简单条件判断&#xff0c;比if判断标签少些不等于相同功能&#xff0c;视个人习惯而用。 用法&#xff1a; {eyou:switch name$eyou.field.has_children} {eyou:case value1}当前栏目列表的栏目ID有1个下级栏目{/eyo…

跨境电商卖家如何应对拒付、盗卡

跨境电商主要是通过电子商务平台进行交易&#xff0c;在平台上完成支付结算&#xff0c;并通过国际物流将商品送达买方&#xff0c;从而实现跨国零售交易。与传统贸易相比&#xff0c;跨境电商存在交易链条更短、回款周期更快、数据及时透明等优势。商务部数据显示&#xff0c;…

sumifs的交叉 表的例子

比如这样&#xff0c;那么冰箱绿山店的栏位中&#xff0c;SUMIFS($D$3:$D$10,$B$3:$B$10,$F3,$C$3:$C$10,G$2)就是把求和范围&#xff0c;条件1设置为固定列的复合引用&#xff0c;条件2设置为固定行的复合引用即可。

LeetCode 1653. Minimum Deletions to Make String Balanced【字符串,动态规划,枚举】中等

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

shell基本知识

为什么学习和使用Shell编程 什么是Shell shell的起源 shell的功能 shell的分类 如何查看当前系统支持的shell&#xff1f; 如何查看当前系统默认shell&#xff1f; 驼峰语句 shell脚本的基本元素 shell脚本编写规范 shell脚本的执行方式 shell脚本的退出状态 &#xf…