goroutine传参 有点可怕
1.背景
我昨天写一个需求,老版本继续跑它的逻辑,新版本我Go出去,看看新老版本对比结果,之所以Go出去是因为担心影响线上服务,比如不用Go出去,如果代码异常或者阻塞,就会影响老版本逻辑的执行,因此这里采用Goroutine的方式去处理。
2.代码
3.上线跑起来
goroutine报错了。
4.上网解决
上网搜索了之后才明白:
新开goroutine的可用堆栈空间默认分配2k的内存
故传入的参数不宜过大,否则导致程序panic
5. 解决办法
改为指针类型传递 减少传递参数的大小,只传入需要使用的参数 去除协程
我采用的就是第一种,改为指针类型传递。
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一定要小心,参数不易过大,否则上线之后头就大了。另外就是看源码,写的很明白,避坑指南要收藏好!
文章转载自堆栈future,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。






