并发使我们能够独立处理多个任务。 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中文网其他相关文章!

掌握Go语言中的strings包可以提高文本处理能力和开发效率。1)使用Contains函数检查子字符串,2)用Index函数查找子字符串位置,3)Join函数高效拼接字符串切片,4)Replace函数替换子字符串。注意避免常见错误,如未检查空字符串和大字符串操作性能问题。

你应该关心Go语言中的strings包,因为它能简化字符串操作,使代码更清晰高效。1)使用strings.Join高效拼接字符串;2)用strings.Fields按空白符分割字符串;3)通过strings.Index和strings.LastIndex查找子串位置;4)用strings.ReplaceAll进行字符串替换;5)利用strings.Builder进行高效字符串拼接;6)始终验证输入以避免意外结果。

thestringspackageingoisesential forefficientstringManipulation.1)itoffersSimpleyetpoperfulfunctionsFortaskSlikeCheckingSslingSubstringsStringStringsStringsandStringsN.2)ithandhishiCodeDewell,withFunctionsLikestrings.fieldsfieldsfieldsfordsforeflikester.fieldsfordsforwhitespace-fieldsforwhitespace-separatedvalues.3)3)

WhendecidingbetweenGo'sbytespackageandstringspackage,usebytes.Bufferforbinarydataandstrings.Builderforstringoperations.1)Usebytes.Bufferforworkingwithbyteslices,binarydata,appendingdifferentdatatypes,andwritingtoio.Writer.2)Usestrings.Builderforstrin

Go的strings包提供了多种字符串操作功能。1)使用strings.Contains检查子字符串。2)用strings.Split将字符串分割成子字符串切片。3)通过strings.Join合并字符串。4)用strings.TrimSpace或strings.Trim去除字符串首尾的空白或指定字符。5)用strings.ReplaceAll替换所有指定子字符串。6)使用strings.HasPrefix或strings.HasSuffix检查字符串的前缀或后缀。

使用Go语言的strings包可以提升代码质量。1)使用strings.Join()优雅地连接字符串数组,避免性能开销。2)结合strings.Split()和strings.Contains()处理文本,注意大小写敏感问题。3)避免滥用strings.Replace(),考虑使用正则表达式进行大量替换。4)使用strings.Builder提高频繁拼接字符串的性能。

Go的bytes包提供了多种实用的函数来处理字节切片。1.bytes.Contains用于检查字节切片是否包含特定序列。2.bytes.Split用于将字节切片分割成smallerpieces。3.bytes.Join用于将多个字节切片连接成一个。4.bytes.TrimSpace用于去除字节切片的前后空白。5.bytes.Equal用于比较两个字节切片是否相等。6.bytes.Index用于查找子切片在largerslice中的起始索引。

theEncoding/binarypackageingoisesenebecapeitProvidesAstandArdArdArdArdArdArdArdArdAndWriteBinaryData,确保Cross-cross-platformCompatibilitiational and handhandlingdifferentendenness.itoffersfunctionslikeread,写下,写,dearte,readuvarint,andwriteuvarint,andWriteuvarIntforPreciseControloverBinary


热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

SublimeText3 英文版
推荐:为Win版本,支持代码提示!

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

Atom编辑器mac版下载
最流行的的开源编辑器

记事本++7.3.1
好用且免费的代码编辑器