在 Go 中轉儲 Goroutine 堆疊跟蹤

Jay Singh 2022年4月22日
在 Go 中轉儲 Goroutine 堆疊跟蹤

處理奇怪情況的慣用方法是在 Go 程式中使用錯誤。錯誤導致軟體中出現的大多數異常情況。

但是,在極少數情況下,軟體將由於異常狀態而無法繼續執行。在這種情況下,panic 可以提前結束程式。

當函式遇到 panic 時,函式的執行將停止,任何延遲的函式都將執行,並且控制權將返回給函式的呼叫者。

這個過程一直持續到所有當前 goroutine 的函式都返回,此時程式在終止之前列印 panic 訊息,然後是堆疊跟蹤。

當我們構建一個示例程式時,這將變得更加清晰。

在 Go 中使用 panic 轉儲 Goroutine 堆疊跟蹤

這個簡單的指令碼將列印一個人的全名。fullName 函式返回一個人的全名。

此方法檢查 firstNamelastName 指標中的 nil 值。如果它是 nil,該函式會傳送一個帶有訊息的 panic 訊號。

當程式完成時,它將列印此訊息。

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

輸出:

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

現在,下面的示例犯了一個常見錯誤,即嘗試使用內建 len 提供的長度來訪問切片的最終元素。

為了說明為什麼這可能會導致恐慌,請執行以下程式碼。

package main

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

輸出:

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

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