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

goroutine传参 有点可怕

1.背景

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

2.代码

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

3.上线跑起来

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

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

原文始发于微信公众号(堆栈future):goroutine传参panic,原因在源码中找到了

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/103476.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!