How do you get a Golang program to print the line number of the error it just called?

后端 未结 3 508
南方客
南方客 2020-12-12 12:40

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 r

相关标签:
3条回答
  • 2020-12-12 12:59

    Short version, there's nothing directly built in, 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.
            _, fn, line, _ := runtime.Caller(1)
            log.Printf("[error] %s:%d %v", fn, 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, fn, line, _ := runtime.Caller(1)
    
            log.Printf("[error] in %s[%s:%d] %v", runtime.FuncForPC(pc).Name(), fn, line, err)
            b = true
        }
        return
    }
    
    func main() {
        if FancyHandleError(fmt.Errorf("it's the end of the world")) {
            log.Print("stuff")
        }
    }
    

    playground

    0 讨论(0)
  • 2020-12-12 13:12

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

    And here is the output:

    0 讨论(0)
  • 2020-12-12 13:17

    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)
    
    0 讨论(0)
提交回复
热议问题