当前位置: 首页 > 科技观察

Go1.17新特性,优化抛出的错误堆栈

时间:2023-03-19 17:59:14 科技观察

转载本文请联系脑筋急转弯公众号。大家好,我是炸鱼。在日常工程中,我们经常会用到异常恐慌(panic)的记录和跟踪。最常见的是,在网络恐慌之后,我们总想寻找一些蛛丝马迹。我们很多人看着panic,看看他的调用栈。然后开始猜,看代码。猜猜是不是写的有问题,我想知道是什么参数引起的panic?因为知道了诱导参数,所以很方便排查问题。为此,在Go1.17中,官方优化了这个调用栈信息的显示,使其更具可读性。该案例结合我们平时使用的panic案例。如下:funcmain(){example(make([]string,1,2),"friedfish",3)}//go:noinlinefuncexample(slice[]string,strstring,iint)error{panic("ThebrainisfriedThefishisgone")}运行结果:$gorunmain.gopanic:brainfriedfishgoroutine1[running]:main.example(0xc000032758,0x1,0x2,0x1073d11,0x6,0x3,0xc000102058,0x1013201)/Users/eddycjy/go-application/awesomeProject/main.go:9+0x39main.main()/Users/eddycjy/go-application/awesomeProject/main.go:4+0x68exitstatus2我们函数的输入参数是:[]string,string,int,核心关注main.example方法的调用栈信息:main.example(0xc000032758,0x1,0x2,0x1073d11,0x6,0x3,0xc000102058,0x1013201)明明只是函数的三个参数,却输出了一堆,对应关系很不清楚。它的实际对应是:slice:0xc000032758,0x1,0x2。字符串:0x1073d11、0x6。整数:0x3。这里的问题是,看调用栈的人必须了解基本的数据结构(例如:slice、string、int等),这样他才能知道每个函数有多少个字段作为参数,然后他可以知道它的内存布局结构有点麻烦。而且从程序运行的角度来看,这样的横向平铺方式并不直观准确。因为类型不同,所以将多个字段组合成一个结构体来表示一个类型。这得人为估计?优化最后,这块的调用栈视图在Go1.17正式得到了改进。如下:$go1.17runmain.gopanic:脑炸鱼goroutine1[running]:main.example({0x0,0xc0000001a0,0xc000034770},{0x1004319,0x60},0x0)/Users/eddycjy/go-application/awesomeProject/main.go:9+0x27main.main()/Users/eddycjy/go-application/awesomeProject/main.go:4+0x47exitstatus2新版本调用栈信息发生变化:main.example({0x0,0xc0000001a0,0xc000034770},{0x1004319,0x60},0x0)在以前版本的Go语言中,调用栈中的函数参数根据内存布局打印为十六进制值,读取困难。Go1.17之后,每个函数的参数会单独打印,并用“,”隔开,复合数据类型(如:结构体、数组、切片等)的参数会用花括号括起来,即整体更具可读性。实际对应如下:slice:0x0,0xc0000001a0,0xc000034770。字符串:0x1004319、0x60。整数:0x0。这里还有一个细节需要注意。你会发现Go1.17的函数参数数量比之前的版本少了。是因为函数的返回值存在于寄存器中,并没有保存在内存中。因此,函数的返回值可能不准确,所以在新版本中不再打印。总结在Go1.17新版??本中,对调用栈函数参数的可读性进行了进一步的优化和调整,可能会在后续使用中带来一定的排错效率提升。您通常使用调用堆栈来排查问题,您希望得到哪些其他帮助?参考GoTip:NewStackTraceOutputWrongcmd/compile:badtracebackargumentsGo1.17newfeaturesindetail:useregister-basedcallingconventionsdoc/go1.17:reword"results"instacktraceprinting