在 Go 中转储 Goroutine 堆栈跟踪
Jay Singh
2022年4月22日
处理奇怪情况的惯用方法是在 Go 程序中使用错误。错误导致软件中出现的大多数异常情况。
但是,在极少数情况下,软件将由于异常状态而无法继续运行。在这种情况下,panic
可以提前结束程序。
当函数遇到 panic
时,函数的执行将停止,任何延迟的函数都将运行,并且控制权将返回给函数的调用者。
这个过程一直持续到所有当前 goroutine 的函数都返回,此时程序在终止之前打印 panic
消息,然后是堆栈跟踪。
当我们构建一个示例程序时,这将变得更加清晰。
在 Go 中使用 panic
转储 Goroutine 堆栈跟踪
这个简单的脚本将打印一个人的全名。fullName
函数返回一个人的全名。
此方法检查 firstName
和 lastName
指针中的 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