假设我有这样的代码:
value, err := some3rdpartylib.DoSomething()
if err != nil {
panic(err)
}
在err != nil
的情况下,我会得到这样的结果:
panic: some error explanation here
goroutine 1 [running]:
main.main()
/tmp/blabla/main.go:6 +0x80
这个堆栈跟踪是完全合法的,但有时这些错误消息可能无法澄清发生了什么,所以我想深入挖掘第三方库的源代码,以调查究竟是什么导致这个错误被返回。但是,当我的代码像这样死机时,没有办法获得返回此错误的实际位置。
再澄清一点:由于我来自JVM世界,在那里异常被抛出,我可以完全跟踪到底是哪行代码抛出了异常,因此可以很容易地找到位置并查看出了什么问题。Go堆栈跟踪正好在我的代码出现异常的地方结束,因此在我的情况下不是很有用。
我创建了一个playground here,理想情况下,我希望能够跟踪错误到它实际返回的位置,而不是恐慌。(例如,到第17行,return "", errors.New("some error explanation here")
)
这可能吗
8条答案
按热度按时间nhn9ugyo1#
我认为有一个更简单的方法来实现这一点。您可以使用golang“default”第三方库错误包尝试wrapping errors:
您需要定义
error
要实现的接口:然后在 Package /处理错误时使用它:
根据mrpandey的评论,还有其他允许一定程度的错误处理的库:
8fsztsew2#
简而言之:这是不可能的。由于errors are values,它们不会以任何特殊的方式处理。因此,当函数(通常)返回时,堆栈不再可用(即。另一个函数调用可以重写返回错误函数堆栈所使用的存储器)。
go1.5中引入了一个名为 trace 的工具,但目前还没有全面的教程,我发现的任何教程都没有说会包含这种功能。
mftmpeh83#
正如其他人所指出的,在go中跟踪错误并不简单。有一些像juju/errgo这样的项目,允许您 Package 错误,然后跟踪这些错误。为了让它工作得坚韧,你必须在整个项目中一致地使用它们,这对你处理第三方库中的错误或处理后永远不会返回的错误没有帮助。
因为这是一个很常见的问题,我真的对此很恼火,我写了一个小的debug utility,它将添加调试代码到go文件中,记录每个返回的错误(实现
error
的值)以及返回到STDOUT的函数(如果你需要更高级的日志记录,只需在项目中破解日志记录器,这真的很简单)。安装
用法
要调试当前目录中的所有文件,请执行以下操作:
要从go文件中删除添加的调试代码,请执行以下操作:
然后只需简单地编译并运行您的代码或测试用例。
输出示例
从这个输出中可以看出,很容易判断错误最初发生在哪个函数中。一旦知道了这一点,就可以使用调试器来获取更多的上下文。
kknvjkwl4#
查看https://github.com/ztrue/tracerr
我创建这个包是为了同时拥有堆栈跟踪和源代码片段,以便能够更快地调试并记录更多详细信息的错误。
下面是一个代码示例:
下面是输出:
1szpjjfi5#
问题是标准包
errors
没有在堆栈跟踪发生的时候附加堆栈跟踪。您可以使用github.com/pkg/errors来执行以下操作:更多详情:https://dave.cheney.net/2016/06/12/stack-traces-and-the-errors-package
aij0ehis6#
请看:https://github.com/efimovalex/stackerr
这是你在找的东西吗?
结果:
myss37ts7#
据我所知,stackrerror是最简单的堆栈显示包。您可以使用所有本机日志库记录或自己输出调用堆栈。例如:
输出:
new9mtju8#
您可以使用内置的Recover函数来处理死机并打印堆栈跟踪。
从https://blog.golang.org/defer-panic-and-recover
Recover是一个内置函数,可以重新控制一个惊慌失措的goroutine。Recover仅在延迟函数中有用。在正常执行期间,调用recover将返回nil,并且没有其他效果。如果当前的goroutine是panicking,调用recover将捕获panic的值并恢复正常执行。
我修改了你的例子,使用recover和eris。Eris提供了一种更好的方法来处理,跟踪和记录Go中的错误。
输出为:
在这里查看它的实际应用https://play.golang.org/p/jgkaR42ub5q