Go conc库学习与使用
文章目录
- 主要功能和特点
- `conc` 的安装
- 典型使用场景
- 示例代码
- 并行执行多个 Goroutines
- 错误处理
- 限制并发 Goroutines 数量
- 使用 `context.Context` 进行任务控制
- 常见问题
- 1. **任务中发生 `panic`**
- 原因:
- 解决方法:
- 2. **`conc.Group` 重复调用 `Wait()`**
- 原因:
- 解决方法:
- 3. **在 `Wait()` 之前修改任务**
- 原因:
- 解决方法:
- 4. **`context` 被取消或超时导致的 `panic`**
- 原因:
- 解决方法:
- 5. **并发访问共享资源引发的 `panic`**
- 原因:
- 解决方法:
- 学习与使用建议
- 总结
sourcegraph/conc 是由 Sourcegraph 开发的并发控制库,用于 Go 语言中更方便地管理和协调 Goroutines。
conc 旨在简化 Go 并发编程,提供更直观的 API 来处理并发操作,尤其是 Goroutines 的生命周期管理、错误处理以及资源安全访问。
主要功能和特点
-
Group 协调 Goroutines:
conc提供了一种GroupAPI,可以帮助管理多个 Goroutines 的并行执行,类似于sync.WaitGroup,但提供了更多的高级特性,例如错误处理和结果收集。
-
并发任务控制:
conc的Group可以控制任务的并发度,确保不会过多创建 Goroutines,避免过度并发导致系统压力。
-
自动错误处理和结果收集:
conc提供了内置的错误处理机制,每个 Goroutine 的错误都能被安全地收集到,避免了 Go 中手动编写错误通道的麻烦。同时,conc还可以收集并发任务的返回结果。
-
上下文支持:
conc可以与context.Context一起使用,支持超时、取消等控制。
-
简洁易用:
- 与 Go 标准库相比,
conc提供了简洁且易用的 API,降低了并发编程的复杂性。
- 与 Go 标准库相比,
conc 的安装
可以通过 go get 来安装 conc 库:
go get github.com/sourcegraph/conc
典型使用场景
-
并行执行多个 Goroutines 并等待它们完成:
使用conc.Group来管理多个 Goroutine,可以确保主 Goroutine 等待所有并发任务完成。 -
错误收集和处理:
可以自动收集并发 Goroutines 中的错误,并提供一个统一的处理机制。 -
限制并发数:
控制 Goroutines 的并发数量,防止系统过载。
示例代码
并行执行多个 Goroutines
这是一个简单的示例,演示如何使用 conc.Group 来并行执行多个 Goroutines:
package mainimport ("context""fmt""log""time""github.com/sourcegraph/conc"
)func main() {// 创建一个 conc.Group 来管理并发任务var group conc.Group// 添加多个并发任务for i := 0; i < 5; i++ {i := i // 避免闭包引用问题group.Go(func() {// 模拟一些工作time.Sleep(time.Duration(i) * time.Second)fmt.Printf("Task %d completed\n", i)})}// 等待所有任务完成if err := group.Wait(); err != nil {log.Fatalf("Error occurred: %v", err)}fmt.Println("All tasks completed")
}
错误处理
如果 Goroutines 可能返回错误,conc.Group 提供了错误收集功能:
package mainimport ("errors""fmt""log""time""github.com/sourcegraph/conc"
)func main() {var group conc.Group// 向 group 添加多个并发任务,其中某个任务会返回错误for i := 0; i < 5; i++ {i := igroup.Go(func() error {time.Sleep(time.Duration(i) * time.Second)if i == 3 {return errors.New("error in task 3")}fmt.Printf("Task %d completed\n", i)return nil})}// 等待所有任务完成,并捕获错误if err := group.Wait(); err != nil {log.Fatalf("Error occurred: %v", err)}fmt.Println("All tasks completed successfully")
}
限制并发 Goroutines 数量
通过 conc.LimitedGroup,可以限制同时运行的 Goroutines 数量:
package mainimport ("context""fmt""log""time""github.com/sourcegraph/conc"
)func main() {// 创建一个 LimitedGroup,限制并发 Goroutines 的数量为 3group := conc.NewLimitedGroup(3)// 添加多个并发任务for i := 0; i < 10; i++ {i := igroup.Go(func() {// 模拟一些工作time.Sleep(time.Second)fmt.Printf("Task %d completed\n", i)})}// 等待所有任务完成if err := group.Wait(); err != nil {log.Fatalf("Error occurred: %v", err)}fmt.Println("All tasks completed")
}
在这个例子中,即使我们添加了 10 个 Goroutines,实际上只有 3 个任务会同时执行,其余任务会等待前面的任务完成后再继续执行。
使用 context.Context 进行任务控制
conc.Group 支持与 context.Context 一起使用,可以处理任务的超时和取消操作:
package mainimport ("context""fmt""log""time""github.com/sourcegraph/conc"
)func main() {// 创建一个带有超时的 contextctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)defer cancel()// 创建一个 conc.Groupvar group conc.Groupgroup.WithContext(ctx)// 添加并发任务for i := 0; i < 5; i++ {i := igroup.Go(func() error {time.Sleep(2 * time.Second)fmt.Printf("Task %d completed\n", i)return nil})}// 等待任务完成或超时if err := group.Wait(); err != nil {log.Fatalf("Error occurred: %v", err)}fmt.Println("All tasks completed or context timed out")
}
如果任务在超时时间内没有完成,则会自动取消未执行完的任务。
常见问题
在使用 sourcegraph/conc 时,虽然库本身已经提供了简化并发编程的 API,并且在设计上避免了一些常见的错误,但仍然有可能会遇到一些 panic 问题。以下是一些可能会遇到的 panic 情况,以及相应的原因和解决方案:
1. 任务中发生 panic
由于 conc.Group 中的每个任务实际上是一个 Goroutine,因此如果某个任务内部发生了 panic,默认情况下整个进程都会终止。这是 Go 语言中的常见现象。如果一个任务中出现了未捕获的运行时错误(如数组越界、空指针引用等),会导致 panic。
原因:
- 任务函数内有运行时错误,例如空指针访问、除零等。
解决方法:
- 在任务中使用
recover来捕获panic,以防止程序崩溃。
示例:
package mainimport ("fmt""log""time""github.com/sourcegraph/conc"
)func main() {var group conc.Groupfor i := 0; i < 3; i++ {i := igroup.Go(func() {defer func() {if r := recover(); r != nil {log.Printf("Recovered from panic in task %d: %v\n", i, r)}}()if i == 2 {// 模拟一个panicpanic("something went wrong")}time.Sleep(time.Second)fmt.Printf("Task %d completed\n", i)})}if err := group.Wait(); err != nil {log.Fatalf("Error occurred: %v", err)}fmt.Println("All tasks completed")
}
在这个示例中,recover() 会捕获任务中的 panic,防止整个程序崩溃。
2. conc.Group 重复调用 Wait()
conc.Group 设计用于管理一组并发 Goroutines,并在调用 Wait() 时阻塞直到所有 Goroutines 完成。如果你尝试多次调用 Wait(),会引发 panic,因为 conc.Group 只能等待 Goroutines 一次。
原因:
- 调用
group.Wait()后,试图再次调用Wait()。
解决方法:
- 确保每个
conc.Group的Wait()只调用一次。如果需要重新启动并发任务,应该创建一个新的conc.Group实例。
示例:
var group conc.Group
group.Go(func() {time.Sleep(time.Second)
})
group.Wait()// 再次调用会触发 panic
// group.Wait() // 不能重复调用 Wait
3. 在 Wait() 之前修改任务
如果你在调用 Wait() 后,试图向 conc.Group 中添加新的任务,可能会引发 panic。这是因为 conc.Group 一旦进入等待状态,就不能再接受新的任务。
原因:
- 在调用
group.Wait()后,继续调用group.Go()添加任务。
解决方法:
- 确保所有任务在调用
Wait()之前都已经添加完毕。如果需要重新添加任务,应该创建一个新的conc.Group。
示例:
package mainimport ("fmt""log""time""github.com/sourcegraph/conc"
)func main() {var group conc.Groupgroup.Go(func() {time.Sleep(time.Second)fmt.Println("Task 1 completed")})if err := group.Wait(); err != nil {log.Fatalf("Error occurred: %v", err)}// 不能在 Wait() 后添加任务,否则会 panic// group.Go(func() { fmt.Println("New Task") })
}
4. context 被取消或超时导致的 panic
在与 context.Context 一起使用时,如果 context 被取消或超时,任务可能会提前终止。如果没有正确处理这种情况,可能会导致 panic,尤其是在任务依赖外部资源或状态时。
原因:
context被取消后,某些任务未能正确处理取消信号,继续执行。
解决方法:
- 在任务中检查
context.Context是否被取消,并正确处理任务的中止。可以通过ctx.Done()来监听context的取消信号。
示例:
package mainimport ("context""fmt""log""time""github.com/sourcegraph/conc"
)func main() {ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)defer cancel()var group conc.Groupgroup.WithContext(ctx)for i := 0; i < 3; i++ {i := igroup.Go(func() error {select {case <-time.After(3 * time.Second): // 任务超时长于 context 超时fmt.Printf("Task %d completed\n", i)case <-ctx.Done(): // 处理 context 取消fmt.Printf("Task %d canceled due to context timeout\n", i)return ctx.Err()}return nil})}if err := group.Wait(); err != nil {log.Printf("Error occurred: %v\n", err)}
}
在这个例子中,当 context 超时时,任务会被正确取消,并不会继续运行。
5. 并发访问共享资源引发的 panic
尽管 conc.Group 本身并不会引发与共享资源相关的 panic,但如果任务中不安全地并发访问共享变量或资源,仍可能导致数据竞争或 panic。
原因:
- 多个 Goroutines 同时访问或修改共享资源而未使用适当的同步机制。
解决方法:
- 使用同步机制(如
sync.Mutex)来保护对共享资源的访问,避免数据竞争。
示例:
package mainimport ("fmt""sync""time""github.com/sourcegraph/conc"
)func main() {var group conc.Groupvar mu sync.Mutex // 保护共享资源count := 0for i := 0; i < 5; i++ {group.Go(func() {time.Sleep(1 * time.Second)mu.Lock() // 锁定共享资源count++mu.Unlock() // 解锁})}group.Wait()fmt.Printf("Final count: %d\n", count)
}
在这个示例中,通过 sync.Mutex 锁定共享资源 count,避免了可能的数据竞争或 panic。
学习与使用建议
- 多线程任务协调:在需要同时执行多个任务时,可以通过
conc.Group轻松管理。 - 错误处理:如果需要捕捉每个 Goroutine 的执行错误,可以利用
conc.Group的内置错误处理机制。 - 并发限制:当系统对并发量有上限时,
conc.LimitedGroup是非常有用的工具,可以帮助控制 Goroutines 数量。 - 与上下文配合:在需要任务超时、取消等场景时,建议结合
context.Context使用。
总结
sourcegraph/conc 是一个简化 Go 并发编程的高效工具库。它提供了比标准库更简洁、更功能丰富的 API,能够更好地处理 Goroutines 的错误、结果以及并发数量控制。同时,它还集成了 context,适合处理超时和取消任务的场景。
sourcegraph/conc 设计简单且安全,但在使用过程中,开发者仍需注意 Goroutines 常见的并发问题。常见的 panic 情况包括任务中的运行时错误、重复调用 Wait()、context 超时、以及不安全的并发访问。通过正确的任务管理、错误处理和同步机制,可以有效避免这些问题。
相关文章:
Go conc库学习与使用
文章目录 主要功能和特点conc 的安装典型使用场景示例代码并行执行多个 Goroutines错误处理限制并发 Goroutines 数量使用 context.Context 进行任务控制 常见问题1. **任务中发生 panic**原因:解决方法: 2. **conc.Group 重复调用 Wait()**原因…...
大模型prompt先关
对于未出现的任务,prompt编写技巧: 1、假设你是资深的摘要生成专家,根据提供的内容,总结对应的摘要信息。请生成一个指令,指令中带有一个使用例子。直接提供给大型模型以执行此任务。 2、基于大模型提供的内容再进行二…...
尚品汇-自动化部署-Jenkins的安装与环境配置(五十六)
目录: 自动化持续集成 (1)环境准备 (2)初始化 Jenkins 插件和管理员用户 (3)工作流程 (4)配置 Jenkins 构建工具 自动化持续集成 互联网软件的开发和发布…...
【尚跑】2024铜川红色照金半程马拉松赛,大爬坡152安全完赛
1、赛事背景 2024年9月22日8点,2024铜川红色照金半程马拉松赛于照金1933广场鸣枪起跑! 起跑仪式上,6000位选手们合唱《歌唱祖国》,熟悉的旋律响彻陕甘边革命根据地照金纪念馆前,激昂的歌声凝聚心中不变的热爱。随着国…...
WPS中让两列数据合并的方法
有这样一个需求,就是把A列数据和B列数据进行合并(空单元格略过)具体实现效果如图下: 该如何操作呢? 首先在新的一列第一个单元格中输入公式"A1&B1" 然后回车,就出现了两列单元格数据合并的效…...
使用yum为centos系统安装软件以及使用(包含阿里云yum源配置)
centos系统配置阿里云yum源 因为centos7官方停止维护,自带yum源用不了了,所以可以更换成阿里云yum源 方法: 使用root权限执行以下语句 curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo CentOS…...
《深度学习》【项目】OpenCV 发票识别 透视变换、轮廓检测解析及案例解析
目录 一、透视变换 1、什么是透视变换 2、操作步骤 1)选择透视变换的源图像和目标图像 2)确定透视变换所需的关键点 3)计算透视变换的变换矩阵 4)对源图像进行透视变换 5)对变换后的图像进行插值处理 二、轮廓检测…...
Linux 线程互斥
前言 对于初学线程的伙伴来讲,多线程并发访问导致的数据不一致问题,总是让人陷入怀疑,很多人只是给你说加锁!但没有人告诉你为什么?本篇博客将详解! 目录 前言 一、线程互斥 • 为什么票会出现负数的情…...
【Redis 源码】6AOF持久化
1 AOF功能说明 aof.c 文件是 Redis 中负责 AOF(Append-Only File)持久化的核心文件。AOF 持久化通过记录服务器接收到的每个写命令来实现数据的持久化。这样,在 Redis 重启时,可以通过重放这些命令来恢复数据。 2 AOF相关配置 a…...
6.MySQL基本查询
目录 表的增删查改Insert(插入)插入替换插入替换2 Retrieve(查找)SELECT 列全列查找指定列查询查询字段为表达式为查询结果指定别名结果去重 WHERE 条件order by子句筛选分页结果 Update(更新)delete&#…...
Linux字符设备驱动开发
Linux 字符设备驱动开发是内核模块开发中的一个重要部分,主要用于处理字节流数据设备(如串口、键盘、鼠标等)。字符设备驱动的核心任务是定义如何与用户空间程序交互,通常通过一组文件操作函数进行。这些函数会映射到 open、read、…...
HTML5+JavaScript绘制闪烁的网格错觉
HTML5JavaScript绘制闪烁的网格错觉 闪烁的网格错觉(scintillating grid illusion)是一种视觉错觉,通过简单的黑白方格网格和少量的精心设计,能够使人眼前出现动态变化的效果。 闪烁的栅格错觉,是一种经典的视觉错觉…...
每日OJ题_牛客_拼三角_枚举/DFS_C++_Java
目录 牛客_拼三角_枚举/DFS 题目解析 C代码1 C代码2 Java代码 牛客_拼三角_枚举/DFS 拼三角_枚举/DFS 题目解析 简单枚举,不过有很多种枚举方法,这里直接用简单粗暴的枚举方式。 C代码1 #include <iostream> #include <algorithm> …...
[uni-app]小兔鲜-01项目起步
项目介绍 效果演示 技术架构 创建项目 HBuilderX创建 下载HBuilderX编辑器 HBuilderX/创建项目: 选择模板/选择Vue版本/创建 安装插件: 工具/插件安装/uni-app(Vue3)编译器 vue代码不能直接运行在小程序环境, 编译插件帮助我们进行代码转换 绑定微信开发者工具: 指定微信开…...
安全的价值:构建现代企业的基础
物理安全对于组织来说并不是事后才考虑的问题:它是关键的基础设施。零售商、医疗保健提供商、市政当局、学校和所有其他类型的组织都依赖安全系统来保障其人员和场所的安全。 随着安全技术能力的不断发展,许多组织正在以更广泛的视角看待他们的投资&am…...
门面(外观)模式
简介 门面模式(Facade Pattern)又叫作外观模式,提供了一个统一的接口,用来访问子系统中的一群接口。其主要特征是定义了一个高层接口,让子系统更容易使用,属于结构型设计模式。 通用模板 创建子系统角色类…...
kotlin flow 使用
1 创建flow 方式1 通过携程扩展函数FlowKt中的flow扩展函数可以直接构建flow,只需要传递FlowCollector收集器实现类就可以了 private fun create1(){val intFlow createFlow()println("创建int flow: $intFlow")runBlocking {println("开始收集&…...
vue3 实现文本内容超过N行折叠并显示“...展开”组件
1. 实现效果 组件内文字样式取决与外侧定义 组件大小发生变化时,文本仍可以省略到指定行数 文本不超过时, 无展开,收起按钮 传入文本发生改变后, 组件展示新的文本 2. 代码 文件名TextEllipsis.vue <template><div ref"compRef" class"wq-text-ellip…...
根据源码解析Vue2中对于对象的变化侦测
UI render(state) VUE的特点是数据驱动视图,在这里可以把数据理解为状态,而视图就是用户可以看到的页面,页面是动态变化的,而他的变化或是用户操作引起,或是后端数据变化引起,这些都可以说是数据的状态变…...
爬虫技术深潜:探究 JsonPath 与 XPath 的语法海洋与实战岛屿
Python爬虫中JSON与XML字符串的XPath和JsonPath过滤语法区别对比 在信息爆炸的互联网时代,数据抓取成为了获取宝贵信息的关键技能。对于技术爱好者,特别是Python程序员来说,熟练掌握JSON和XML数据解析方法至关重要。本文旨在深入探讨这两种格…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
Linux系统部署KES
1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘…...
破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...
