英文:
Trick to quickly find file & line number throwing an error in Go?
问题
在我使用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
解析为一个映射类型的Go值,因为它是一个数组。我们必须将其解析为interface{}
以支持数组和映射。然而,它没有告诉我哪个文件/行导致了这个错误。
问题:
- 有没有一种快速找到错误来源的方法?
- 一般来说,Go语言开发者有没有什么技巧可以从这个字符串错误消息中快速找到问题的源头?
- 大多数Go项目的堆栈跟踪是这样的吗?还是有一些应该遵循的最佳实践?
英文:
In my journey with go discovered that there are no stacktraces. so whenever something breaks, all we get an simple string error message without any information where is this is coming from. This is in stark contrast with other languages where I am used to seing detailed stacktraces
For example, below is the error message from apex
$ cat event.json | apex invoke --logs webhook
⨯ error parsing response: json: cannot unmarshal array into Go value of type map[string]interface {}
here its telling me that unmarshal to a map ins't working because event.json
is an array. We have unmarshal to interface{}
to support both arrays & maps.However, it doesn't tell me which file/line is causing this error.
Questions:
- What is way to quickly find which file/line this error coming from?
- In General, Are there tips/tricks which gophers use to get to the source of problem quickly from this string error message?
- is this how stack traces are for most go projects or there are any best practices that should be followed?
答案1
得分: 5
寻找错误来源的快速方法是什么?
除非是未恢复的 panic,否则不会打印默认的堆栈信息。
一般来说,有几种方法可以快速找到问题的源代码。大多数情况下,你需要检查函数调用的错误返回值。有多种方法可以做到这一点。
我通常使用标准库中的 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)
}
}
输出:
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
英文:
> What is way to quickly find which file/line this error coming from?
There are no default stacks printed unless it's an unrecovered panic.
> In General, Are there tips/tricks which gophers use to get to the source of problem quickly from this string error message? is this how stack traces are for most go projects or there are any best practices that should be followed?
In General, you need to check error returns from most of the function calls. There are more than one way to do that.
I usually use standard library package log
to print out error logs with file and line numbers for easy debugging in simple programs. For example:
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
output:
2009/11/10 23:00:00 main.go:14: error
Also, there are functions for you to print or retrieve current stacks in standard library runtime/debug
, e.g. https://golang.org/pkg/runtime/debug/#PrintStack
There are many community efforts on bringing error handling easier, you can search error in GoDoc: https://godoc.org/?q=error
答案2
得分: 2
你尝试的解决方案: 找到产生错误的代码片段来修复代码。
你实际的问题: event.json
的内容。
<sub>这被称为X-Y-Problem</sub>
Invoke 期望一个 JSON 对象,而你传递了一个 JSON 数组。修复这个问题,你的问题就解决了!
$ echo -n '{ "value": "Tobi the ferret" }' | apex invoke uppercase
相关文档的部分内容:调用函数
这是产生错误的代码片段:Github
是的,Go 有堆栈跟踪!阅读Dave Cheney关于错误和异常的博文。
英文:
Your attempted solution: Finding the piece of code that produces the error to fix the code.
Your actual problem: The content of event.json
.
<sub>This is called the X-Y-Problem</sub>
Invoke expects a json object, you are passing a json array. Fix that and your problem is gone!
$ echo -n '{ "value": "Tobi the ferret" }' | apex invoke uppercase
Relevant part of the documentation: Invoking Functions
And that's the piece of code that produces the error: Github
And yes, Go does have stack traces! Read Dave Cheneys blog post on errors and exceptions.
答案3
得分: 1
Go在发生panic
时确实会生成堆栈跟踪并使程序崩溃。这种情况通常发生在代码直接调用panic()
的情况下,比如:
if err != nil {
panic("it broke")
}
或者在运行时发生错误的情况下,比如:
a := []int{1, 2, 3}
b := a[12] // 超出索引范围
以下是一个最简示例:
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
,它指示了文件名和行号。
在你的示例中,程序没有发生panic,而是选择调用(我猜)os.Exit(1)
或log.Fatal("error message")
(它调用os.Exit(1)
)。或者,panic在调用函数中被恢复了。如果你不是代码的作者,对此你无能为力。
我建议阅读Golang博客上的Defer, Panic, and Recover以了解更多信息。
英文:
Go does produce stack traces when a panic
happens, crashing the program. This will happen if the code calls panic()
directly, typically in cases like:
if err != nil {
panic("it broke")
}
or, when a runtime error happens:
a := []int{1, 2, 3}
b := a[12] // index out of range
Here's a minimal example:
package main
func main() {
panic("wtf?!")
}
Output:
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
Note the main.go:4
indicating the filename and line number.
In your example, the program did not panic, instead opting to call (I'm guessing) os.Exit(1)
or log.Fatal("error message")
(which calls os.Exit(1)
). Or, the panic was simply recovered from in the calling function. Unfortunately, there's nothing you can do about this if you aren't the author of the code.
I would recommend reading Defer, Panic, and Recover on the Golang blog for more about this.
答案4
得分: 0
在main()函数中设置log.SetFlags(log.LstdFlags | log.Lshortfile)
即可。
例如,log.Printf("Deadline!")
将打印:
03/11/2020 23:59:59 liberty_test.go:42: Deadline!
英文:
Setting log.SetFlags(log.LstdFlags | log.Lshortfile)
in main() should do it.
For example, log.Printf("Deadline!")
would print:
> 03/11/2020 23:59:59 liberty_test.go:42: Deadline!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论