0

0

如何使用Golang实现goroutine并发执行_Golang goroutine并发控制方法汇总

P粉602998670

P粉602998670

发布时间:2026-01-24 08:24:09

|

936人浏览过

|

来源于php中文网

原创

goroutine泄漏典型表现为内存持续上涨且runtime.NumGoroutine()只增不减;常见原因包括channel未关闭致接收阻塞、ticker未Stop;可通过pprof查看堆栈,检查for range ch是否确保channel关闭,以及ticker是否配对Stop。

如何使用golang实现goroutine并发执行_golang goroutine并发控制方法汇总

goroutine 泄漏的典型表现和快速定位方法

启动大量 goroutine 但程序内存持续上涨、runtime.NumGoroutine() 返回值只增不减,基本可判定存在 goroutine 泄漏。常见原因是 channel 未关闭导致接收方永久阻塞,或 timer/ticker 未 Stop()

  • pprof 查看 goroutine 堆
    curl 'http://localhost:6060/debug/pprof/goroutine?debug=2'
  • 检查所有 for range ch 循环——必须确保 ch 会被关闭,否则接收协程永远卡在 recv 状态
  • 所有 time.Ticker 必须配对 ticker.Stop(),尤其在 select + case 场景下

用 sync.WaitGroup 控制固定任务集的并发完成

sync.WaitGroup 适合「已知数量、无需超时、不关心返回值」的并发场景,比如批量写文件、并行初始化服务。它不提供取消或错误传播能力。

  • 必须在 goroutine 启动前调用 wg.Add(1),不能在 goroutine 内部调用(竞态风险)
  • wg.Done() 应放在 defer 中,避免 panic 导致计数器未减少
  • 不要在循环里重复声明 var wg sync.WaitGroup——每次都要重置计数器,否则 Wait() 可能提前返回
var wg sync.WaitGroup
for _, url := range urls {
    wg.Add(1)
    go func(u string) {
        defer wg.Done()
        http.Get(u) // 实际逻辑
    }(url)
}
wg.Wait() // 阻塞直到全部完成

用 context.WithTimeout 管理带超时的并发请求

当并发调用外部 API 或数据库,并需要统一超时控制时,context.WithTimeout 是比 time.After 更安全的选择——它能主动取消子 goroutine 的阻塞操作(如 http.Client 支持 context)。

Pixie.haus
Pixie.haus

AI像素图像生成平台

下载
  • 不要把同一个 context.Context 传给多个独立 goroutine 后再调用 cancel()——这会同时中断所有,应为每个 goroutine 创建子 context
  • HTTP 请求务必使用 http.NewRequestWithContext(ctx, ...),原生 http.Get 不响应 cancel
  • ctx.Err() 在超时后为 context.DeadlineExceeded,可据此区分超时与其他错误
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

var wg sync.WaitGroup
for _, url := range urls {
    wg.Add(1)
    go func(u string) {
        defer wg.Done()
        req, _ := http.NewRequestWithContext(ctx, "GET", u, nil)
        client := &http.Client{}
        resp, err := client.Do(req)
        if err != nil {
            if errors.Is(err, context.DeadlineExceeded) {
                log.Printf("timeout for %s", u)
            }
            return
        }
        resp.Body.Close()
    }(url)
}
wg.Wait()

用 errgroup.Group 替代手写错误收集与取消

标准库 errgroup.Group 封装了 sync.WaitGroup + context + 错误传播,适用于「并发执行、任一失败即终止、需返回首个错误」的场景,比如微服务多依赖调用。

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

  • 必须用 eg.Go(func() error { ... }) 启动任务,不能用 go 关键字直接起 goroutine
  • 首次非 nil 错误会自动触发 ctx.Cancel(),后续 goroutine 应检查 ctx.Err() 主动退出
  • 如果所有 goroutine 都没返回错误,eg.Wait() 返回 nil;否则返回第一个非 nil 错误
g, ctx := errgroup.WithContext(context.Background())
for _, task := range tasks {
    task := task // 避免循环变量捕获
    g.Go(func() error {
        select {
        case <-time.After(task.Delay):
            return nil
        case <-ctx.Done():
            return ctx.Err()
        }
    })
}
if err := g.Wait(); err != nil {
    log.Fatal(err) // 第一个出错的任务
}
实际并发控制最易被忽略的是:**goroutine 生命周期与资源释放的耦合关系**。比如开 goroutine 读 channel,却忘了 close;启了 http.Server 却没处理 Shutdown();用了 os.Pipe() 却没 close write end —— 这些都会让 goroutine 挂住,且很难通过日志察觉。

相关专题

更多
golang如何定义变量
golang如何定义变量

golang定义变量的方法:1、声明变量并赋予初始值“var age int =值”;2、声明变量但不赋初始值“var age int”;3、使用短变量声明“age :=值”等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

180

2024.02.23

golang有哪些数据转换方法
golang有哪些数据转换方法

golang数据转换方法:1、类型转换操作符;2、类型断言;3、字符串和数字之间的转换;4、JSON序列化和反序列化;5、使用标准库进行数据转换;6、使用第三方库进行数据转换;7、自定义数据转换函数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

228

2024.02.23

golang常用库有哪些
golang常用库有哪些

golang常用库有:1、标准库;2、字符串处理库;3、网络库;4、加密库;5、压缩库;6、xml和json解析库;7、日期和时间库;8、数据库操作库;9、文件操作库;10、图像处理库。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

340

2024.02.23

golang和python的区别是什么
golang和python的区别是什么

golang和python的区别是:1、golang是一种编译型语言,而python是一种解释型语言;2、golang天生支持并发编程,而python对并发与并行的支持相对较弱等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

209

2024.03.05

golang是免费的吗
golang是免费的吗

golang是免费的。golang是google开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的开源编程语言,采用bsd开源协议。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

393

2024.05.21

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

198

2025.06.09

golang相关判断方法
golang相关判断方法

本专题整合了golang相关判断方法,想了解更详细的相关内容,请阅读下面的文章。

191

2025.06.10

golang数组使用方法
golang数组使用方法

本专题整合了golang数组用法,想了解更多的相关内容,请阅读专题下面的文章。

273

2025.06.17

c++空格相关教程合集
c++空格相关教程合集

本专题整合了c++空格相关教程,阅读专题下面的文章了解更多详细内容。

0

2026.01.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 4.1万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号