你如何让一个 Golang 程序打印出刚刚调用的错误所在的行号?

huangapple go评论80阅读模式
英文:

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..."

人们对我的代码了解得越少越好 你如何让一个 Golang 程序打印出刚刚调用的错误所在的行号?

英文:

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 你如何让一个 Golang 程序打印出刚刚调用的错误所在的行号?

答案1

得分: 165

你可以在自定义的日志记录器或默认日志记录器上设置标志,以包括LlongfileLshortfile

// 修改默认日志记录器的标志
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")
    }
}

playground

英文:

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&#39;re using 1, so it will actually log where
		// the error happened, 0 = this function, we don&#39;t want that.
		_, filename, line, _ := runtime.Caller(1)
		log.Printf(&quot;[error] %s:%d %v&quot;, 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&#39;re using 1, so it will actually log the where
		// the error happened, 0 = this function, we don&#39;t want that.
		pc, filename, line, _ := runtime.Caller(1)

		log.Printf(&quot;[error] in %s[%s:%d] %v&quot;, runtime.FuncForPC(pc).Name(), filename, line, err)
		b = true
	}
	return
}

func main() {
	if FancyHandleError(fmt.Errorf(&quot;it&#39;s the end of the world&quot;)) {
		log.Print(&quot;stuff&quot;)
	}
}

<kbd>playground</kbd>

答案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)
}

以下是输出结果:
你如何让一个 Golang 程序打印出刚刚调用的错误所在的行号?

英文:

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 (
	&quot;io/ioutil&quot;
	&quot;github.com/ztrue/tracerr&quot;
)

func main() {
	if err := read(); err != nil {
		tracerr.PrintSourceColor(err)
	}
}

func read() error {
	return readNonExistent()
}

func readNonExistent() error {
	_, err := ioutil.ReadFile(&quot;/tmp/non_existent_file&quot;)
	// Add stack trace to existing error, no matter if it&#39;s nil.
	return tracerr.Wrap(err)
}

And here is the output:
你如何让一个 Golang 程序打印出刚刚调用的错误所在的行号?

huangapple
  • 本文由 发表于 2014年7月18日 00:50:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/24809287.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定