为了账号安全,请及时绑定邮箱和手机立即绑定

如何获取指向实际错误原因的堆栈跟踪

如何获取指向实际错误原因的堆栈跟踪

Go
呼啦一阵风 2021-11-15 15:42:44
假设我有一些这样的代码:value, err := some3rdpartylib.DoSomething()if err != nil {    panic(err)}万一err != nil我会得到这样的东西:panic: some error explanation heregoroutine 1 [running]:main.main()    /tmp/blabla/main.go:6 +0x80此堆栈跟踪是完全合法的,但有时这些错误消息可能无法说明发生了什么,因此我想深入研究 3rd 方库的源代码,以调查究竟是什么原因导致返回此错误。但是,当我的代码像这样发生混乱时,无法获得返回此错误的实际位置。稍微澄清一点:因为我来自抛出异常的 JVM 世界,所以我可以完全跟踪抛出异常的代码行到底是哪一行,因此可以轻松找到位置并查看出了什么问题。Go 堆栈跟踪正好在我的代码发生混乱的地方结束,因此在我的情况下不太有用。我在这里创建了一个操场,理想情况下我希望能够将错误追溯到它实际返回的地方,而不是恐慌。(例如第 17 行,return "", errors.New("some error explanation here"))这甚至可能吗?
查看完整描述

3 回答

?
撒科打诨

TA贡献1934条经验 获得超2个赞

我认为有一种更简单的方法可以实现这一目标。您可以尝试包装错误使用golang“默认”的第三方库的错误包:


您需要定义要由您实现的接口error:


type stackTracer interface {

    StackTrace() errors.StackTrace

}

然后在包装/处理错误时使用它:


err, ok := errors.(stackTracer) // ok is false if errors doesn't implement stackTracer


stack := err.StackTrace()

fmt.Println(stack) // here you'll have your stack trace


查看完整回答
反对 回复 2021-11-15
?
炎炎设计

TA贡献1808条经验 获得超4个赞

很快:这是不可能的。由于错误是值,因此不会以任何特殊方式处理它们。因此,当函数(通常)返回时,堆栈不再可用(即另一个函数调用可能会覆盖返回错误函数的堆栈使用的内存)。

go1.5 中引入了一个名为trace的工具,但目前,没有可用的综合教程,我发现的任何一个都没有说将包含此类功能。


查看完整回答
反对 回复 2021-11-15
?
红颜莎娜

TA贡献1842条经验 获得超12个赞

正如其他人指出的那样,跟踪 go 中的错误并非易事。有像juju/errgo这样的项目,它允许您包装错误,然后追溯这些错误。为了让它工作起来很艰难,您必须在整个项目中始终如一地使用它们,这不会帮助您解决 3rd 方库中的错误或处理后永远不会返回的错误。


因为这是一个很常见的问题,我真的对此很恼火,所以我编写了一个小型调试实用程序,它将向 go 文件添加调试代码,该文件记录每个返回的错误(实现的值error)以及将其返回到 STDOUT 的函数(如果您需要更高级的日志记录,只需在项目中 hack 记录器,这真的很简单)。


安装


go get github.com/gellweiler/errgotrace

用法


要调试当前目录中的所有文件:


$ find . -name '*.go' -print0 | xargs -0 errgotrace -w

从 go 文件中删除添加的调试代码:


$ find . -name '*.go' -print0 | xargs -0 errgotrace -w -r

然后只需简单地编译和运行您的代码或您的测试用例。


样本输出


[...]

2017/12/13 00:54:39 [ERRGOTRACE] parser.*Parser.objectKey: EOF token found

2017/12/13 00:54:39 [ERRGOTRACE] parser.*Parser.objectItem: EOF token found

2017/12/13 00:54:39 [ERRGOTRACE] parser.*Parser.objectKey: EOF token found

2017/12/13 00:54:39 [ERRGOTRACE] parser.*Parser.objectItem: EOF token found

2017/12/13 00:54:39 [ERRGOTRACE] parser.*Parser.objectKey: At 3:4: nested object expected: LBRACE got: ASSIGN

2017/12/13 00:54:39 [ERRGOTRACE] parser.*Parser.objectItem: At 3:4: nested object expected: LBRACE got: ASSIGN

2017/12/13 00:54:39 [ERRGOTRACE] parser.*Parser.objectList: At 3:4: nested object expected: LBRACE got: ASSIGN

2017/12/13 00:54:39 [ERRGOTRACE] parser.*Parser.Parse: At 2:31: literal not terminated

2017/12/13 00:54:39 [ERRGOTRACE] parser.Parse: At 2:31: literal not terminated

2017/12/13 00:54:39 [ERRGOTRACE] hcl.parse: At 2:31: literal not terminated

2017/12/13 00:54:39 [ERRGOTRACE] hcl.ParseBytes: At 2:31: literal not terminated

2017/12/13 00:54:39 [ERRGOTRACE] formula.parse: parsing failed

[...]

从这个输出中可以看出,很容易判断错误最初发生在哪个函数中。一旦你知道了,你就可以使用调试器来获得更多的上下文。


查看完整回答
反对 回复 2021-11-15
  • 3 回答
  • 0 关注
  • 226 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信