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

快速查找文件和行号在 Go 中抛出错误的技巧?

快速查找文件和行号在 Go 中抛出错误的技巧?

Go
天涯尽头无女友 2021-12-20 10:17:34
在我与 go 的旅程中发现没有堆栈跟踪。所以每当出现问题时,我们都会收到一条简单的字符串错误消息,而没有任何信息来自哪里。这与我习惯于查看详细堆栈跟踪的其他语言形成鲜明对比例如,下面是来自apex的错误消息$ cat event.json | apex invoke --logs webhook                                      ⨯ error parsing response: json: cannot unmarshal array into Go value of type map[string]interface {}这里它告诉我解组到地图不起作用,因为它event.json是一个数组。我们已经解组到interface{}支持数组和映射。但是,它没有告诉我哪个文件/行导致了这个错误。问题:有什么方法可以快速找到此错误来自哪个文件/行?一般来说,地鼠是否有提示/技巧可以从这个字符串错误消息中快速找到问题的根源?这是大多数 go 项目的堆栈跟踪方式,还是应该遵循任何最佳实践?
查看完整描述

3 回答

?
GCT1015

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

有什么方法可以快速找到此错误来自哪个文件/行?


除非是无法恢复的恐慌,否则不会打印默认堆栈。


一般来说,地鼠是否有提示/技巧可以从这个字符串错误消息中快速找到问题的根源?这是大多数 go 项目的堆栈跟踪方式,还是应该遵循任何最佳实践?


通常,您需要检查大多数函数调用的错误返回。有不止一种方法可以做到这一点。我通常使用标准库包log打印带有文件和行号的错误日志,以便在简单程序中进行调试。例如:


package main


import "log"

import "errors"


func init() { log.SetFlags(log.Lshortfile | log.LstdFlags) }


func callFunc() error {

    return errors.New("error")

}


func main() {

    if err := callFunc(); err != nil {

        log.Println(err)

    }

}

http://play.golang.org/p/0iytNw7eZ7


输出:


2009/11/10 23:00:00 main.go:14: error

此外,还有一些功能可以打印或检索标准库中的当前堆栈runtime/debug,例如https://golang.org/pkg/runtime/debug/#PrintStack


有许多社区努力使错误处理更容易,您可以在 GoDoc 中搜索错误:https ://godoc.org/ ? q = error


查看完整回答
反对 回复 2021-12-20
?
ABOUTYOU

TA贡献1812条经验 获得超5个赞

您尝试的解决方案查找产生错误的代码段以修复代码。

您的实际问题的内容event.json

这称为XY 问题


Invoke 需要一个 json 对象,您正在传递一个 json 数组。解决这个问题,你的问题就消失了!

$ echo -n '{ "value": "Tobi the ferret" }' | apex invoke uppercase

文档的相关部分:调用函数

这就是产生错误的代码:Github


是的,Go 确实有堆栈跟踪!阅读Dave Cheneys 关于错误和异常的博文


查看完整回答
反对 回复 2021-12-20
?
慕田峪4524236

TA贡献1875条经验 获得超5个赞

当 a发生时,Go确实会产生堆栈跟踪panic,从而使程序崩溃。如果代码panic()直接调用就会发生这种情况,通常在以下情况下:


if err != nil {

    panic("it broke")

}

或者,当发生运行时错误时:


a := []int{1, 2, 3}

b := a[12] // index out of range

这是一个最小的例子:


package main


func main() {

    panic("wtf?!")

}

输出:


panic: wtf?!


goroutine 1 [running]:

panic(0x94e60, 0x1030a040)

    /usr/local/go/src/runtime/panic.go:464 +0x700

main.main()

    /tmp/sandbox366642315/main.go:4 +0x80

注意main.go:4指示文件名和行号。


在您的示例中,程序没有恐慌,而是选择调用(我猜)os.Exit(1)或log.Fatal("error message")(调用os.Exit(1))。或者,恐慌只是从调用函数中恢复。不幸的是,如果您不是代码的作者,则对此无能为力。



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

添加回答

举报

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