goroutine传参panic,原因在源码中找到了

简介: goroutine传参panic,原因在源码中找到了

goroutine传参 有点可怕



1.背景


我昨天写一个需求,老版本继续跑它的逻辑,新版本我Go出去,看看新老版本对比结果,之所以Go出去是因为担心影响线上服务,比如不用Go出去,如果代码异常或者阻塞,就会影响老版本逻辑的执行,因此这里采用Goroutine的方式去处理。


2.代码


640.png


3.上线跑起来

640.png


goroutine报错了。


4.上网解决


上网搜索了之后才明白:


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


5. 解决办法


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


我采用的就是第一种,改为指针类型传递。


6. 源码


// The minimum size of stack used by Go code
 _StackMin = 2048
//go:systemstack
func newproc1(fn *funcval, argp unsafe.Pointer, narg int32, callergp *g, callerpc uintptr) *g {
 _g_ := getg()
 if fn == nil {
  _g_.m.throwing = -1 // do not dump full stacks
  throw("go of nil func value")
 }
 acquirem() // disable preemption because it can be holding p in a local var
 siz := narg
 siz = (siz + 7) &^ 7
 // We could allocate a larger initial stack if necessary.
 // Not worth it: this is almost always an error.
 // 4*sizeof(uintreg): extra space added below
 // sizeof(uintreg): caller's LR (arm) or return address (x86, in gostartcall).
 // 这里有判断 大于2048即2K就panic
 if siz >= _StackMin-4*sys.RegSize-sys.RegSize {
  throw("newproc: function arguments too large for new goroutine")
 }
  ...
}


7. 小结


用goroutine一定要小心,参数不易过大,否则上线之后头就大了。另外就是看源码,写的很明白,避坑指南要收藏好!

相关文章
|
6月前
|
编译器 Go
Golang底层原理剖析之函数调用栈-传参和返回值
Golang底层原理剖析之函数调用栈-传参和返回值
60 0
|
Go C++ 索引
太狠了!原来panic可以直接干掉程序
太狠了!原来panic可以直接干掉程序
110 0
|
17天前
|
存储 Rust Go
Go nil 空结构体 空接口有什么区别?
本文介绍了Go语言中的`nil`、空结构体和空接口的区别。`nil`是预定义的零值变量,适用于指针、管道等类型;空结构体大小为0,多个空结构体实例指向同一地址;空接口由`_type`和`data`字段组成,仅当两者均为`nil`时,空接口才为`nil`。
Go nil 空结构体 空接口有什么区别?
|
3月前
|
Serverless Go
Golang 开发函数计算问题之defer 中的 recover() 没有捕获到 如何解决
Golang 开发函数计算问题之defer 中的 recover() 没有捕获到 如何解决
|
6月前
|
小程序 安全 算法
mPaaS问题之使用小程序传参数报错如何解决
mPaaS小程序是阿里巴巴移动平台服务(mPaaS)推出的一种轻量级应用解决方案,旨在帮助开发者快速构建跨平台的小程序应用;本合集将聚焦mPaaS小程序的开发流程、技术架构和最佳实践,以及如何解决开发中遇到的问题,从而助力开发者高效打造和维护小程序应用。
101 2
|
6月前
|
Java Go
浅谈defer、panic、recover 三者的用法
浅谈defer、panic、recover 三者的用法
43 0
|
6月前
|
C语言
C语言函数传递了指针,值没有被修改的原因及解决方法
C语言函数中传递了指针作为参数,确切来说是传递了指向变量的内存地址作为参数,可经过函数内的修改之后,该指针指向的变量的值为什么不会被修改?就像下方这个函数:
111 1
Mgo
|
Shell Go
go调用shell命令两种方式实现(有无返回值)
go调用shell命令两种方式实现(有无返回值)
Mgo
1591 1
普通函数中的this指向问题解决方案call
普通函数中的this指向问题解决方案call
53 0