Goroutine Stack Traces in Go ausgeben

Jay Singh 23 August 2022
Goroutine Stack Traces in Go ausgeben

Der idiomatische Ansatz zum Umgang mit seltsamen Umständen besteht darin, Fehler in einem Go-Programm zu verwenden. Fehler verursachen die Mehrzahl der ungewöhnlichen Fälle, die in der Software auftreten.

In seltenen Fällen kann die Software jedoch aufgrund eines fehlerhaften Zustands nicht weiter ausgeführt werden. In dieser Situation kann Panik das Programm vorzeitig beenden.

Wenn eine Funktion auf eine Panik trifft, wird die Ausführung der Funktion angehalten, alle verzögerten Funktionen werden ausgeführt, und die Kontrolle wird an den Aufrufer der Funktion zurückgegeben.

Diese Prozedur wird fortgesetzt, bis alle Funktionen der aktuellen Goroutine zurückgekehrt sind. Zu diesem Zeitpunkt gibt das Programm die panic-Meldung und dann den Stack-Trace aus, bevor es beendet wird.

Wenn wir ein Beispielprogramm konstruieren, wird dies klarer.

Goroutine Stack Traces in Go mit panic ausgeben

Dieses einfache Skript gibt den vollständigen Namen einer Person aus. Die Funktion fullName gibt den vollständigen Namen einer Person zurück.

Diese Methode prüft die Zeiger firstName und lastName auf nil-Werte. Wenn es nil ist, sendet die Funktion ein panic-Signal mit einer Meldung.

Wenn das Programm beendet ist, wird diese Nachricht gedruckt.

package main

import (
    "fmt"
)

func fullName(firstName *string, lastName *string) {
    if firstName == nil {
        panic("runtime error: first name cannot be nil")
    }
    if lastName == nil {
        panic("runtime error: last name cannot be nil")
    }
    fmt.Printf("%s %s\n", *firstName, *lastName)
    fmt.Println("returned normally from fullName")
}

func main() {
    firstName := "Jay"
    fullName(&firstName, nil)
    fmt.Println("returned normally from main")
}

Ausgabe:

panic: runtime error: last name cannot be nil

goroutine 1 [running]:
main.fullName(0x405058?, 0xc000070f70?)
    /tmp/sandbox885911142/prog.go:12 +0x114
main.main()
    /tmp/sandbox885911142/prog.go:20 +0x35

Das folgende Beispiel macht nun den üblichen Fehler, auf das letzte Element des Slice zuzugreifen, indem es dessen Länge verwendet, die durch das eingebaute len bereitgestellt wird.

Um zu demonstrieren, warum dies zu Panik führen könnte, führen Sie den folgenden Code aus.

package main

import (
    "fmt"
)
func main() {
    names := []string{
        "Iron Man",
        "Thor",
    }
    fmt.Println("My favorite superhero is:", names[len(names)])
}

Ausgabe:

panic: runtime error: index out of range [2] with length 2

goroutine 1 [running]:
main.main()
    /tmp/sandbox2746930010/prog.go:12 +0x1b