it-swarm.com.de

Wie kann ein Golang-Programm die Zeilennummer des gerade aufgerufenen Fehlers drucken?

Ich habe versucht, Fehler in meinem Golang-Programm mit log.Fatal zu werfen, aber log.Fatal druckt nicht die Zeile, in der der log.Fatal ausgeführt wurde. Gibt es keine Möglichkeit, auf die Zeilennummer zuzugreifen, die log.Fatal genannt hat? Gibt es eine Möglichkeit, die Zeilennummer zu erhalten, wenn ein Fehler ausgelöst wird?

Ich habe versucht, dies zu googeln, war mir aber nicht sicher, wie. Das Beste, was ich bekommen konnte, war das Ausdrucken der Stapelspur , was meiner Meinung nach gut ist, aber vielleicht ein bisschen zu viel ist. Ich möchte auch nicht jedes Mal debug.PrintStack() schreiben, wenn ich die Zeilennummer benötige. Ich bin nur überrascht, dass es keine eingebaute Funktion wie log.FatalStackTrace() gibt oder etwas, das kein Kostüm ist.

Der Grund, aus dem ich kein eigenes Debugging/Fehlerbehandlungs-Material erstellen möchte, ist, dass ich nicht möchte, dass die Leute lernen müssen, wie ich meinen speziellen Code zur Handhabung von Kostümen verwendet. Ich möchte nur etwas Standard, bei dem die Leute meinen Code später lesen und sein können 

"Ah ok, also wirft einen Fehler und macht X ..."

Je weniger Leute über meinen Code erfahren müssen, desto besser :)

68
Pinocchio

Sie können die Flags entweder für einen benutzerdefinierten Logger oder für die Voreinstellung festlegen, dass Llongfile ODER Lshortfile

// to change the flags on the default logger
log.SetFlags(log.LstdFlags | log.Lshortfile)
87
JimB

Kurze Version, da ist nichts direkt eingebautSie können es jedoch mit einer minimalen Lernkurve implementieren, indem Sie runtime.Caller verwenden

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

67
OneOfOne

Wenn Sie genau einen Stack-Trace benötigen, schauen Sie unter https://github.com/ztrue/tracerr nach.

Ich habe dieses Paket erstellt, um sowohl Stack-Trace- als auch Quellfragmente zu haben, um schneller debuggen und Fehler mit viel mehr Details protokollieren zu können.

Hier ist ein Codebeispiel:

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

Und hier ist die Ausgabe:  golang error stack trace

0
Johan