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 踩过的坑之协程参数不能过大

相关推荐
昵称为空C14 分钟前
在复杂SpringBoot项目中基于hutool实现临时添加多数据源案例
spring boot·后端
金融数据出海1 小时前
韩国股票 API 对接指南 Seoul&KOSDAQ
后端
geovindu1 小时前
go: Simple Factory Pattern
开发语言·后端·设计模式·golang·简单工厂模式
咕白m6251 小时前
Python 高效添加与管理 Excel 工作表
后端·python
计算机学姐1 小时前
基于SpringBoot的房屋交易系统
java·vue.js·spring boot·后端·spring·intellij-idea·mybatis
java1234_小锋1 小时前
SpringBoot 4 + Spring Security 7 + Vue3 前后端分离项目设计最佳实践
spring boot·后端·spring
今夕资源网1 小时前
indextts API 阅读 API 重磅升级!低延迟 + 音色管理 + 缓存全拉满 支持开源阅读小说软件,其他软件应该也通用
java·后端·spring
Rick19932 小时前
Spring Cloud 原理是什么?
后端·spring·spring cloud
掘金者阿豪2 小时前
从死守 Windows 到彻底 Mac 化:程序员一旦用了 Mac,真的很难再回去
后端
阿里加多2 小时前
第 5 章:Go 内存模型与 Happens-Before 原则
开发语言·后端·golang