Go 踩过的坑之协程参数不能过大

一、问题

在日常开发过程中,我们通常会使用协程来并发处理数据,比如下面的例子采用 协程 + sync.WaitGroup 来并发处理数据:

从mysql请求的切片数据,遍历后开启协程根据指定字段统计数据,此处采用了协程组的方式提高效率

代码如下:

go 复制代码
//结构体
type RespStruct struct{
    struct01 //内嵌另外的结构体
    struct02 //内嵌另外的结构体
}
func StatisticData(){
    var respData []RespStruct
    var wg sync.WaitGroup
    //1.从mysql查询数据,封装到respData ,代码省略
    //2.循环respData并且开启协程组,添加协程
    for i, d := range respData {
        wg.Add(1)
         go func(req ProduceOrderProcessQueryRespParam) {
            defer func() {
                wg.Done()
            }()
            //打印参数
             fmt.Println(req)
            return
        }(d)
    }
    wg.wait()
    fmt.Println("end.....")
}

输出报错:

fatal error: newproc: function arguments too large for new goroutine

二、原因

由于结构体嵌结构体,变成新的比较大的结构体d。那么在启动新协程的时候,又因为是值传递,新copy了一份d的副本,导致参数超过了新goroutine的可用堆栈空间。 goroutine默认分配2k的内存

三、解决:

  • 1.改为指针类型传递(推荐)
  • 2.减少传递参数的大小,只传入需要使用的参数(推荐)
  • 3.去除协程

四、修改:

将协程 的匿名函数修改为函数调用方式;代码修改如下

go 复制代码
//结构体
type RespStruct struct{
    struct01 //内嵌另外的结构体
    struct02 //内嵌另外的结构体
}
func StatisticData(){
    var respData []RespStruct
    var wg sync.WaitGroup
    //1.从mysql查询数据,封装到respData ,代码省略
    //2.循环respData并且开启协程组,添加协程
    for i, d := range respData {
        wg.Add(1)
         go func(req *ProduceOrderProcessQueryRespParam) {
            defer func() {
                wg.Done()
            }()
            //打印参数
             fmt.Println(req)
            return
        }(&d)
    }
    wg.wait()
    fmt.Println("end.....")
}

正常输出

五、总结

该报错的主要原因:新开 goroutine 的可用堆栈空间默认分配2k的内存 故传入的参数不宜过大,否则导致程序panic

解决方法也很简单,只需要通过指针引用的方式即可解决

原文地址

Go 踩过的坑之协程参数不能过大

相关推荐
葫芦和十三20 小时前
图解 MongoDB 30|查询路由与广播查询:带片键定向,不带就广播
后端·mongodb·agent
葫芦和十三20 小时前
图解 MongoDB 29|分片键陷阱:jumbo chunk、孤儿文档和写入热点
后端·mongodb·agent
进击的程序猿~20 小时前
Go Zero源码阅读1
后端·golang
2601_961593421 天前
Rust 开发环境配置繁琐?RustRover 开箱即用搞定编码调试
开发语言·后端·macos·rust
犀利豆1 天前
AI in Harness(三)
人工智能·后端
IT_陈寒1 天前
Java的Stream.parallel()把我CPU跑爆了,这种优化要谨慎
前端·人工智能·后端
子兮曰1 天前
Bun 重写为 Rust:11天、64个Claude、16.5万美元,一次改变行业认知的激进实验
前端·后端·bun
子兮曰1 天前
Node.js v26.5.0 深度解读:import Text、流式 ReadableStreamTee、以及隐藏的安全加固浪潮
前端·后端·node.js
子兮曰1 天前
TypeScript 7.0 RC 深度解读:Go 重写完成,10 倍提速,编译器的「奇点时刻」
前端·后端·typescript
kosan1 天前
.NET/C# 实战:我如何把登录验证码从“裸奔”改到“铜墙铁壁”
后端