搜索
首页后端开发GolangGoroutines 和 Channels:Go 中的并发模式

并发使我们能够独立处理多个任务。 Goroutine 是一种独立处理多个任务的简单方法。在这篇文章中,我们逐步增强了一个 http 处理程序,该处理程序接受文件,并利用通道和同步包探索 Go 中的各种并发模式。

设置

在进入并发模式之前,让我们先做好准备。想象一下,我们有一个 HTTP 处理程序,它通过表单接受多个文件并以某种方式处理这些文件。

func processFile(file multipart.File) {
   // do something with the file
   fmt.Println("Processing file...")
   time.Sleep(100 * time.Millisecond) // Simulating file processing time
}
func UploadHandler(w http.ResponseWriter, r *http.Request) {
   // limit to 10mb 
   if err := r.ParseMultipartForm(10 



<p>在上面的示例中,我们从表单接收文件并按顺序处理它们。如果上传 10 个文件,则需要 1 秒才能完成该过程并向客户端发送响应。 <br>
当处理许多文件时,这可能会成为瓶颈,但是通过 Go 的并发支持,我们可以轻松解决这个问题。</p>
<h2>
  
  
  等待组
</h2>

<p>为了解决这个问题,我们可以并发处理文件。要生成一个新的 goroutine,我们可以在函数调用前加上 go 关键字,例如去处理文件(f)。然而,由于 goroutine 是非阻塞的,处理程序可能会在进程完成之前返回,从而导致文件可能未处理或返回不正确的状态。要等待所有文件的处理,我们可以使用sync.WaitGroup。<br>
WaitGroup 等待多个 goroutine 完成,对于我们生成的每个 goroutine,我们还应该增加 WaitGroup 中的计数器,这可以通过 Add 函数来完成。当 goroutine 完成时,应该调用 Done,以便计数器减一。在从函数返回之前,应该调用 Wait,该函数会阻塞,直到 WaitGroup 的计数器为 0。<br>
</p>

<pre class="brush:php;toolbar:false">func UploadHandler(w http.ResponseWriter, r *http.Request) {
   if err := r.ParseMultipartForm(10 



<p>现在,对于每个上传的文件,都会生成一个新的 goroutine,这可能会压垮系统。一种解决方案是限制生成的 goroutine 的数量。</p>

<h2>
  
  
  使用信号量限制并发
</h2>

<p>信号量只是一个变量,我们可以用它来控制多个线程(或者在本例中为 goroutine)对公共资源的访问。<br><br>
在 Go 中,我们可以利用缓冲通道来实现信号量。</p>
<h3>
  
  
  渠道
</h3>

<p>在进入实现之前,我们先来看看什么是通道以及缓冲通道和非缓冲通道之间的区别。 </p>

<p>通道是一个管道,我们可以通过它发送和接收数据,以便在 go 例程之间安全地通信。<br>
通道必须使用 make 函数创建。<br>
</p><pre class="brush:php;toolbar:false">
func processFile(file multipart.File) {
   // do something with the file
   fmt.Println("Processing file...")
   time.Sleep(100 * time.Millisecond) // Simulating file processing time
}
func UploadHandler(w http.ResponseWriter, r *http.Request) {
   // limit to 10mb 
   if err := r.ParseMultipartForm(10 



<p>通道有一个特殊的运算符
让操作员指向通道 ch <br>
<img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/173404051364120.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="Goroutines and Channels: Concurrency Patterns in Go"><br>
该动画形象地展示了生产者通过无缓冲通道发送值 1 以及消费者从该通道读取数据的情况。</p>

<p>如果生产者发送事件的速度比消费者处理的速度快,那么我们可以选择利用<strong>缓冲通道</strong>来排队多个消息,而不会阻塞生产者,直到缓冲区已满。同时,消费者可以按照自己的节奏处理消息。<br>
</p>

<pre class="brush:php;toolbar:false">func UploadHandler(w http.ResponseWriter, r *http.Request) {
   if err := r.ParseMultipartForm(10 



<p>在此示例中,生产者最多可以发送两个项目而不会阻塞。当缓冲区达到容量时,生产者将阻塞,直到消费者处理了至少一条消息。 </p>

<p><img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/173404051459967.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="Goroutines and Channels: Concurrency Patterns in Go"></p>

<p>回到最初的问题,我们要限制同时处理文件的 goroutine 数量。为此,我们可以利用缓冲通道。<br>
</p>

<pre class="brush:php;toolbar:false">ch := make(chan int)

在此示例中,我们添加了一个容量为 5 的缓冲通道,这使我们能够同时处理 5 个文件并限制系统压力。

但是如果并非所有文件都相等怎么办?我们可以可靠地预测不同的文件类型或文件大小需要更多的资源来处理。在这种情况下,我们可以使用加权信号量。

加权信号量

简单地说,使用加权信号量,我们可以为单个任务分配更多资源。 Go 已经在扩展同步包中提供了加权信号量的实现。

ch := make(chan int, 2)

在此版本中,我们创建了一个具有 5 个槽的加权信号量,如果仅上传图像,例如进程会同时处理 5 个图像,但是如果上传 PDF,则会获取 2 个槽,这将减少可处理的文件量同时。

结论

我们探索了 Go 中的一些并发模式,利用sync.WaitGroup 和信号量来控制并发任务的数量。然而,还有更多可用的工具,我们可以利用通道来创建工作池、添加超时或使用扇入/扇出模式。
此外,错误处理是一个重要方面,但为了简单起见,大多数情况下都忽略了这一点。
处理错误的一种方法是利用通道来聚合错误并在所有 goroutine 完成后处理它们。

Go 还提供了 errgroup.Group ,它与sync.WaitGroups 相关,但添加了对返回错误的任务的处理。
该包可以在扩展同步包中找到。

以上是Goroutines 和 Channels:Go 中的并发模式的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
Golang和Python:了解差异Golang和Python:了解差异Apr 18, 2025 am 12:21 AM

Golang和Python的主要区别在于并发模型、类型系统、性能和执行速度。1.Golang使用CSP模型,适用于高并发任务;Python依赖多线程和GIL,适合I/O密集型任务。2.Golang是静态类型,Python是动态类型。3.Golang编译型语言执行速度快,Python解释型语言开发速度快。

Golang vs.C:评估速度差Golang vs.C:评估速度差Apr 18, 2025 am 12:20 AM

Golang通常比C 慢,但Golang在并发编程和开发效率上更具优势:1)Golang的垃圾回收和并发模型使其在高并发场景下表现出色;2)C 通过手动内存管理和硬件优化获得更高性能,但开发复杂度较高。

Golang:云计算和DevOps的关键语言Golang:云计算和DevOps的关键语言Apr 18, 2025 am 12:18 AM

Golang在云计算和DevOps中的应用广泛,其优势在于简单性、高效性和并发编程能力。1)在云计算中,Golang通过goroutine和channel机制高效处理并发请求。2)在DevOps中,Golang的快速编译和跨平台特性使其成为自动化工具的首选。

Golang和C:了解执行效率Golang和C:了解执行效率Apr 18, 2025 am 12:16 AM

Golang和C 在执行效率上的表现各有优势。1)Golang通过goroutine和垃圾回收提高效率,但可能引入暂停时间。2)C 通过手动内存管理和优化实现高性能,但开发者需处理内存泄漏等问题。选择时需考虑项目需求和团队技术栈。

Golang vs. Python:并发和多线程Golang vs. Python:并发和多线程Apr 17, 2025 am 12:20 AM

Golang更适合高并发任务,而Python在灵活性上更有优势。1.Golang通过goroutine和channel高效处理并发。2.Python依赖threading和asyncio,受GIL影响,但提供多种并发方式。选择应基于具体需求。

Golang和C:性能的权衡Golang和C:性能的权衡Apr 17, 2025 am 12:18 AM

Golang和C 在性能上的差异主要体现在内存管理、编译优化和运行时效率等方面。1)Golang的垃圾回收机制方便但可能影响性能,2)C 的手动内存管理和编译器优化在递归计算中表现更为高效。

Golang vs. Python:申请和用例Golang vs. Python:申请和用例Apr 17, 2025 am 12:17 AM

selectgolangforhighpperformanceandcorrency,ifealforBackendServicesSandNetwork程序; selectpypypythonforrapiddevelopment,dataScience和machinelearningDuetoitsverserverserverserversator versator anderticality andextility andextentensivelibraries。

Golang vs. Python:主要差异和相似之处Golang vs. Python:主要差异和相似之处Apr 17, 2025 am 12:15 AM

Golang和Python各有优势:Golang适合高性能和并发编程,Python适用于数据科学和Web开发。 Golang以其并发模型和高效性能着称,Python则以简洁语法和丰富库生态系统着称。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前By尊渡假赌尊渡假赌尊渡假赌
威尔R.E.P.O.有交叉游戏吗?
1 个月前By尊渡假赌尊渡假赌尊渡假赌

热工具

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

ZendStudio 13.5.1 Mac

ZendStudio 13.5.1 Mac

功能强大的PHP集成开发环境

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。