英文:
How do you get a Golang program to print the line number of the error it just called?
问题
我正在尝试在我的 Golang 程序中使用 log.Fatal
抛出错误,但是 log.Fatal
并不会打印出调用 log.Fatal
的行号。没有办法获取调用 log.Fatal
的行号吗?也就是说,在抛出错误时,有没有办法获取行号?
我试图在谷歌上搜索这个问题,但是不确定如何操作。我找到的最好的方法是打印堆栈跟踪,我觉得这个方法不错,但可能有点过于繁琐。我也不想每次都写 debug.PrintStack()
来获取行号,我只是惊讶地发现没有内置的函数可以像 log.FatalStackTrace()
这样获取行号,而不需要自定义。
另外,我不想自己编写调试/错误处理的代码,因为我不希望其他人必须学习如何使用我的特殊处理代码。我只想要一些标准的东西,以便其他人以后可以阅读我的代码,并理解:
"啊,好的,所以它抛出一个错误并执行 X..."
人们对我的代码了解得越少越好
英文:
I was trying to throw errors in my Golang program with log.Fatal
but, log.Fatal
does not also print the line where the log.Fatal
was ran. Is there no way of getting access to the line number that called log.Fatal? i.e. is there a way to get the line number when throwing an error?
I was trying to google this but was unsure how. The best thing I could get was printing the stack trace, which I guess is good but might be a little too much. I also don't want to write debug.PrintStack()
every time I need the line number, I am just surprised there isn't any built in function for this like log.FatalStackTrace()
or something that isn't costume.
Also, the reason I do not want to make my own debugging/error handling stuff is because I don't want people to have to learn how to use my special costume handling code. I just want something standard where people can read my code later and be like
> "ah ok, so its throwing an error and doing X..."
The less people have to learn about my code the better
答案1
得分: 165
你可以在自定义的日志记录器或默认日志记录器上设置标志,以包括Llongfile
或Lshortfile
。
// 修改默认日志记录器的标志
log.SetFlags(log.LstdFlags | log.Lshortfile)
英文:
You can set the Flags on either a custom Logger, or the default to include Llongfile
or Lshortfile
// to change the flags on the default logger
log.SetFlags(log.LstdFlags | log.Lshortfile)
答案2
得分: 116
简化版本,没有直接内置的功能,但是你可以使用runtime.Caller
来实现它,而且学习曲线很小。
func HandleError(err error) (b bool) {
if err != nil {
// 注意我们使用的是1,这样它将记录错误发生的位置,0表示此函数,我们不需要那个。
_, filename, line, _ := runtime.Caller(1)
log.Printf("[error] %s:%d %v", filename, line, err)
b = true
}
return
}
// 这也会记录函数名。
func FancyHandleError(err error) (b bool) {
if err != nil {
// 注意我们使用的是1,这样它将记录错误发生的位置,0表示此函数,我们不需要那个。
pc, filename, line, _ := runtime.Caller(1)
log.Printf("[error] in %s[%s:%d] %v", runtime.FuncForPC(pc).Name(), filename, line, err)
b = true
}
return
}
func main() {
if FancyHandleError(fmt.Errorf("it's the end of the world")) {
log.Print("stuff")
}
}
英文:
Short version, <del>there's nothing directly built in</del>, however you can implement it with a minimal learning curve using runtime.Caller
func HandleError(err error) (b bool) {
if err != nil {
// notice that we're using 1, so it will actually log where
// the error happened, 0 = this function, we don't want that.
_, filename, line, _ := runtime.Caller(1)
log.Printf("[error] %s:%d %v", filename, line, err)
b = true
}
return
}
//this logs the function name as well.
func FancyHandleError(err error) (b bool) {
if err != nil {
// notice that we're using 1, so it will actually log the where
// the error happened, 0 = this function, we don't want that.
pc, filename, line, _ := runtime.Caller(1)
log.Printf("[error] in %s[%s:%d] %v", runtime.FuncForPC(pc).Name(), filename, line, err)
b = true
}
return
}
func main() {
if FancyHandleError(fmt.Errorf("it's the end of the world")) {
log.Print("stuff")
}
}
答案3
得分: 5
如果你需要完整的堆栈跟踪,请查看https://github.com/ztrue/tracerr
我创建了这个包,以便能够更快地进行调试并记录更多错误详细信息。
这是一个代码示例:
package main
import (
"io/ioutil"
"github.com/ztrue/tracerr"
)
func main() {
if err := read(); err != nil {
tracerr.PrintSourceColor(err)
}
}
func read() error {
return readNonExistent()
}
func readNonExistent() error {
_, err := ioutil.ReadFile("/tmp/non_existent_file")
// 将堆栈跟踪添加到现有错误中,无论它是否为nil。
return tracerr.Wrap(err)
}
英文:
If you need exactly a stack trace, take a look at https://github.com/ztrue/tracerr
I created this package in order to have both stack trace and source fragments to be able to debug faster and log errors with much more details.
Here is a code example:
package main
import (
"io/ioutil"
"github.com/ztrue/tracerr"
)
func main() {
if err := read(); err != nil {
tracerr.PrintSourceColor(err)
}
}
func read() error {
return readNonExistent()
}
func readNonExistent() error {
_, err := ioutil.ReadFile("/tmp/non_existent_file")
// Add stack trace to existing error, no matter if it's nil.
return tracerr.Wrap(err)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论