Golang协程同步怎么做 sync.WaitGroup实践

WaitGroup用于等待协程完成,通过Add、Done、Wait方法实现同步。示例中启动3个协程,主协程等待其全部完成。

golang协程同步怎么做 sync.waitgroup实践

在Go语言中,协程(goroutine)是实现并发的核心机制。但多个协程并行执行时,主程序可能在协程完成前就退出,导致任务丢失。为解决这个问题,sync.WaitGroup 是最常用的协程同步工具

WaitGroup 是什么?

WaitGroup 用于等待一组协程完成任务。它内部维护一个计数器,通过三个方法控制流程:

Add(n):增加计数器,表示要等待 n 个协程 Done():计数器减1,通常在协程末尾调用 Wait():阻塞主协程,直到计数器归零

基本使用示例

下面是一个简单的例子,启动3个协程并发执行任务,主协程等待它们全部完成:

package mainimport (    "fmt"    "sync"    "time")func worker(id int, wg *sync.WaitGroup) {    defer wg.Done() // 任务完成,计数器减1    fmt.Printf("Worker %d startingn", id)    time.Sleep(time.Second)    fmt.Printf("Worker %d donen", id)}func main() {    var wg sync.WaitGroup    for i := 1; i <= 3; i++ {        wg.Add(1)           // 每启动一个协程,计数+1        go worker(i, &wg)    }    wg.Wait() // 阻塞,直到所有协程调用 Done()    fmt.Println("All workers finished")}

输出结果会是三个 worker 依次打印开始和完成,最后输出 “All workers finished”。

立即学习“go语言免费学习笔记(深入)”;

常见使用技巧和注意事项

使用 WaitGroup 时,有几个关键点要注意,避免死锁或 panic:

确保每个 Add 对应一个 Done,否则 Wait 会一直阻塞 避免在协程中调用 Add,可能导致主协程还没 Wait 就结束 通常将 WaitGroup 指针传入协程函数,避免值拷贝 使用 defer wg.Done() 可确保即使发生 panic 也能正确计数

错误示例(可能导致死锁):

go func() {    wg.Add(1) // ❌ 不应在协程内 Add    defer wg.Done()    // ...}()

正确做法是在 go 之前调用 Add:

wg.Add(1)go func() {    defer wg.Done()    // 任务逻辑}()

实际应用场景

WaitGroup 常用于批量处理任务,比如并发请求多个API、并行处理文件、爬虫抓取等。

例如,同时请求多个外部服务:

urls := []string{"http://example1.com", "http://example2.com"}var wg sync.WaitGroupfor _, url := range urls {    wg.Add(1)    go func(u string) {        defer wg.Done()        resp, err := http.Get(u)        if err != nil {            fmt.Printf("Error: %sn", err)            return        }        fmt.Printf("Success: %s, Status: %sn", u, resp.Status)        resp.Body.Close()    }(url)}wg.Wait()fmt.Println("All requests completed")

基本上就这些。WaitGroup 简单高效,是Go并发编程中最基础也最重要的同步手段之一。用好它,就能安全地管理多个协程的生命周期。

以上就是Golang协程同步怎么做 sync.WaitGroup实践的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1400378.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月15日 16:59:13
下一篇 2025年12月15日 16:59:29

相关推荐

  • Golang二进制瘦身 upx压缩与strip调试

    Go程序编译后体积大是因静态链接包含运行时和依赖库,虽便于部署但文件较大;可通过go build -ldflags=”-s -w”移除调试信息和符号表,再用UPX压缩进一步减小体积;strip不影响程序运行但削弱调试能力,UPX带来轻微启动开销,推荐先strip后upx以获得…

    好文分享 2025年12月15日
    000
  • GAE Datastore Viewer UTF-8 编码错误排查与解决

    在使用 Google App Engine (GAE) Go 运行时进行开发时,如果在 Datastore Viewer 中遇到 UnicodeDecodeError: ‘utf8’ codec can’t decode byte 错误,通常是由于存储到 Data…

    2025年12月15日
    000
  • Go语言GAE Datastore Viewer UTF-8编码错误排查与解决

    本文探讨了在Go语言Google App Engine (GAE) Datastore Viewer中遇到的UTF-8解码错误。该错误通常源于将原始二进制数据(如MD5哈希的字节切片)错误地直接转换为字符串,而不是先进行适当的编码(如十六进制编码)。文章详细解释了encoding/hex包的工作原理…

    2025年12月15日
    000
  • 深入理解Go语言init函数:多文件与多包场景下的初始化策略

    Go语言的init()函数用于包的初始化,它在main()函数执行前自动运行。在多文件和多包的应用结构中,每个包可以拥有自己的init()函数。这些init()函数在独立的包中执行顺序不定,但由于所有初始化代码都在单个goroutine中运行,且对于注册不同的HTTP路由等独立操作,执行顺序无关紧要…

    2025年12月15日
    000
  • 优化 GAE Golang 应用日志:使用 Context 实现可观测性

    在 Google App Engine (GAE) Golang 应用中,直接使用 log.Print() 可能无法在控制台日志中显示调试信息。本文将指导开发者如何利用 GAE 提供的 Context 接口,通过 c.Infof() 等方法实现与平台深度集成的日志记录,确保应用程序的详细调试信息能够…

    2025年12月15日
    000
  • 使用 Go 在 Windows 上启动进程

    在 Go 语言中,启动 Windows 进程主要有两种方式:使用 os 包的 StartProcess 函数,或者使用 os/exec 包的 Cmd 结构体。Cmd 结构体通常被认为更易于使用,因为它提供了更高级别的抽象。 使用 os/exec 包 os/exec 包是 Go 语言标准库中用于执行外…

    2025年12月15日
    000
  • Golang协程错误处理 errchannel收集错误

    使用errchannel可集中处理Go协程中的错误,因goroutine异步执行无法直接返回error,通过带缓冲的error channel将各协程错误发送至主协程统一处理,结合sync.WaitGroup确保所有任务完成,最后关闭channel并遍历获取所有错误,提升并发程序健壮性。 在Go语言…

    2025年12月15日
    000
  • 如何用Golang处理JSON请求 解析请求体与生成响应数据

    使用json.NewDecoder解析JSON请求体并绑定到结构体,2. 通过json.NewEncoder将数据编码为JSON响应,3. 设置Content-Type头并处理错误,确保服务稳定。 在Go语言中处理JSON请求和响应是构建Web服务的常见需求。Golang标准库 encoding/j…

    2025年12月15日
    000
  • Golang环境如何集成Protocol Buffers 安装protoc和go插件指南

    要让 golang 项目顺利使用 protocol buffers,核心步骤是安装 protoc 编译器和对应的 go 插件。1. 安装 protoc 编译器:linux 用户通过下载解压并配置环境变量;macos 使用 homebrew 安装;windows 用户下载 zip 文件并配置路径;最后…

    2025年12月15日 好文分享
    000
  • Golang变量声明有哪些方式 详解var与短声明区别及适用场景

    Golang变量声明主要有var、:=和new三种方式;2. var适用于全局或需显式类型声明的场景,支持多变量批量声明与零值初始化;3. 短声明:=仅限函数内使用,简洁且自动推导类型,适合局部变量快速初始化;4. new用于分配内存并返回指针,常用于需要指针零值的场景,需注意指针操作与作用域控制。…

    2025年12月15日
    000
  • Golang配置管理技巧 环境变量与Viper

    答案:Go应用中通过Viper库结合环境变量实现灵活配置管理,优先级为环境变量 > 配置文件 > 默认值,支持多格式文件解析与结构体绑定,保障配置安全、隔离与可维护性。 在Go语言里,处理配置是个绕不开的话题,尤其当你想让应用灵活、易于部署时。环境变量和Viper库的组合,可以说是目前我…

    2025年12月15日
    000
  • Golang并发编程如何提高性能 合理控制goroutine数量的方法

    合理控制goroutine数量是Go并发性能优化的关键。过多的goroutine会引发调度开销、内存消耗、缓存失效、锁竞争和系统资源耗尽等问题,反而降低性能。应通过有界并发控制避免失控,常用方法包括基于缓冲通道的worker pool模式和基于信号量的并发限制。对于CPU密集型任务,goroutin…

    2025年12月15日
    000
  • 如何优化Golang的锁竞争问题 使用sync.Pool与原子操作替代方案

    优化golang中的锁竞争需从减少共享资源独占时间、采用细粒度同步机制及无锁方案入手。1. 缩小锁粒度,仅对必要数据加锁,如拆分map或使用独立锁;2. 使用sync.pool复用临时对象,降低gc压力从而减少锁竞争;3. 利用atomic包进行原子操作,适用于简单变量的并发安全操作;4. 选用合适…

    2025年12月15日 好文分享
    000
  • Golang的go mod init有什么作用 Golang模块初始化详解

    go mod init 的核心作用是初始化 go 模块并创建 go.mod 文件,具体包括:1. 创建 go.mod 文件作为项目模块的标识;2. 声明模块路径以供其他模块引用;3. 初始化依赖管理机制;4. 启用模块模式以替代传统的 gopath 方式。该命令使项目具备清晰的结构和可靠的依赖管理,…

    2025年12月15日 好文分享
    000
  • Golang如何实现服务网格集成 配置Istio与Envoy代理

    要实现golang服务与istio服务网格集成,核心在于使用envoy边车代理拦截流量,go应用无需感知istio api,只需关注业务逻辑;1. 准备go应用,确保监听端口并实现健康检查端点;2. 编写kubernetes部署文件并启用sidecar注入;3. 配置istio资源如virtuals…

    2025年12月15日 好文分享
    000
  • Go语言内存管理机制_golang内存分配原理

    go语言的内存管理依赖内置垃圾回收器(gc)自动回收不再使用的内存。其内存分配主要发生在堆和栈,栈用于函数调用时的局部变量,由编译器自动管理;堆用于生命周期较长的对象,由gc负责回收。go编译器通过逃逸分析决定变量分配位置,若变量过大或生命周期不确定则会逃逸至堆上。gc采用并发三色标记清除算法,周期…

    2025年12月15日 好文分享
    000
  • Golang如何创建新模块 使用go mod init初始化项目

    答案:go mod init用于初始化Go模块,生成go.mod文件以管理依赖。它标志着项目采用Go Modules机制,摆脱GOPATH限制,实现依赖隔离与版本控制,提升项目可维护性。 在Go语言中,创建一个新模块并使用 go mod init 进行初始化,是现代Go项目开发的起点,它标志着你将采…

    2025年12月15日
    000
  • Golang如何统一处理HTTP错误 设计中间件捕获路由错误

    使用中间件统一处理Go HTTP错误,通过定义ErrorResponse结构和ErrorMiddlewareAdv函数,结合defer/recover捕获panic,推荐用error返回替代panic,实现错误集中处理。 在 Go 的 HTTP 服务中,统一处理错误是提升代码可维护性和 API 一致…

    2025年12月15日
    000
  • Golang错误处理与goroutine 并发环境下的错误收集

    答案:Go并发错误处理需根据场景选择策略。使用channel可基础收集错误,errgroup实现快速失败,结合mutex的切片收集全部错误,引入context控制超时与取消,确保程序健壮性。 在Go语言开发中,错误处理是程序健壮性的关键环节。当程序进入并发场景,尤其是使用大量goroutine时,如…

    2025年12月15日
    000
  • Golang连接池管理 复用网络连接技巧

    连接池通过复用网络连接减少开销,提升高并发下性能。Golang中database/sql包内置连接池,支持配置最大连接数、空闲数和生命周期;自定义连接池需实现获取、归还、健康检查及超时清理机制,常用sync.Mutex保证并发安全。常见陷阱包括连接泄漏、失效连接和配置不当,优化策略涵盖健康检查、合理…

    2025年12月15日
    000

发表回复

登录后才能评论
关注微信