1.panic是什么?
panic 是 Go 语言用于处理运行时严重错误的机制。当 panic 发生时,程序会立即停止执行,并开始回溯(unwind)调用栈,执行所有已注册的 defer 语句,最后终止程序。
2.panic的触发方式
panic 可以通过显式调用 panic() 触发,也可能由于运行时错误(如数组越界、空指针访问等)自动触发。
(1) 显式调用panic
可以在代码中手动调用 panic,用于表示程序遇到了无法继续执行的错误。
示例:
package main
import "fmt"
func main() {
fmt.Println("程序开始")
panic("发生了严重错误!")
fmt.Println("这行代码不会执行")
}
输出:
程序开始
panic: 发生了严重错误!
goroutine 1 [running]:
main.main()
/tmp/sandbox389323384/prog.go:6 +0x40
可以看到 panic 触发后,程序终止,并打印错误信息。
(2) 运行时异常触发panic
有些错误会导致 Go 语言自动触发 panic,例如:
- 数组越界
- 空指针访问
- 除数为零
- 关闭已关闭的通道
示例:
package main
import "fmt"
func main() {
var arr = []int{1, 2, 3}
fmt.Println(arr[5]) // 数组越界,触发 panic
}
输出:
panic: runtime error: index out of range [5] with length 3
程序崩溃,并提示数组越界错误。
3.panic的执行流程
当 panic 触发时,Go 语言会执行以下步骤:
- 立即停止当前函数的执行。
- 回溯调用栈,依次执行所有 defer 语句(如果有)。
- 如果 panic 没有被拦截,程序最终崩溃,并打印 panic 信息及调用栈。
示例:
package main
import "fmt"
func functionA() {
fmt.Println("进入 functionA")
panic("functionA 发生错误")
fmt.Println("离开 functionA") // 这行不会执行
}
func main() {
fmt.Println("程序开始")
functionA()
fmt.Println("程序结束") // 这行不会执行
}
输出:
程序开始
进入 functionA
panic: functionA 发生错误
goroutine 1 [running]:
main.functionA()
/tmp/sandbox389323384/prog.go:6 +0x40
main.main()
/tmp/sandbox389323384/prog.go:12 +0x40
panic 触发后,functionA 立即终止,main 也终止,并打印调用栈信息。
4.panic的使用场景
panic 适用于发生不可恢复的严重错误,如:
- 代码逻辑不应该触发的情况(如非法状态)
- 程序初始化失败(如关键资源不可用)
- 标准库 API 设计(如 log.Panic)
示例:初始化失败时使用 panic
package main
import "fmt"
func initConfig() {
panic("配置文件损坏,无法启动")
}
func main() {
fmt.Println("启动程序")
initConfig() // 触发 panic
fmt.Println("这行不会执行")
}
5.panic与os.Exit的区别
panic 和 os.Exit 都能终止程序,但有以下不同:
特性 | panic | os.Exit |
是否执行 defer | 是 | 否 |
是否回溯调用栈 | 是 | 否 |
是否打印错误信息 | 是 | 否 |
示例:
package main
import (
"fmt"
"os"
)
func main() {
defer fmt.Println("defer 执行")
// os.Exit(1) // 直接退出,defer 不会执行
panic("触发 panic") // 触发 panic,defer 仍然会执行
}
如果使用 os.Exit(1),defer 语句不会执行,而 panic 触发后仍然会执行 defer。
6. 总结
- panic 适用于发生不可恢复的严重错误。
- panic 触发后,会停止当前函数,并回溯调用栈,执行 defer,最终终止程序。
- Go 语言会自动触发 panic(如数组越界、空指针等)。
- panic 和 os.Exit 都能终止程序,但 panic 会执行 defer 并打印错误信息。