学习go语言的时候遇到了两个类似的概念,错误与惊恐,好奇为什么不能统一一哈,于是查询了它们的区别:
- error:是可预见的问题,像走楼梯时不小心绊了一下,你能看到台阶,也知道可能会绊倒,处理一下就好。
- panic:是不可预见的严重故障,像电梯缆绳突然断了,情况失控,程序无法继续运行,只能紧急停机。
error:常规错误处理
error 是 Go 语言官方推荐的常规错误处理机制。它是一个内置接口,定义如下:
type error interface {
Error() string
}特点:
可预期:比如文件不存在、网络超时、用户输入非法等,这些都是写代码时能想到的情况。
显式处理:函数通常会把 error 作为最后一个返回值,调用方必须(或应该)主动检查并处理它。
程序继续:遇到 error,程序不会崩溃,你可以选择重试、记录日志、返回错误给上层等。
error 就是一个普通的值(像 int、string 一样),你可以把它传来传去,也可以自定义错误类型。
file, err := os.Open("test.txt")
if err != nil {
// 处理错误,比如打印日志,返回错误等
fmt.Println("文件打开失败:", err)
return err
}
// 继续正常逻辑...panic:不可恢复的严重错误
panic 是一个内置函数,用于引发一个失控的崩溃场景。
特点:
不可预期:比如数组越界、空指针引用、程序逻辑出现无法处理的矛盾状态等。这些通常是因为 bug 或极其罕见的异常情况。
立即中断:当 panic 发生时,当前函数会立即停止执行,然后沿着调用栈逐级返回,执行沿途的 defer 语句,最后程序崩溃退出。
程序终止:除非用 recover 在 defer 中捕获,否则程序会直接退出。
func divide(a, b int) int {
if b == 0 {
panic("除数不能为0!") // 手动触发 panic
}
return a / b
}捕获一个panic
package main
import "fmt"
func divide(a, b int) int {
if b == 0 {
panic("chu shu bu neng wei 0!")
}
return a / b
}
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("捕获到panic:", r)
}
}()
result := divide(10, 2)
fmt.Println("result is", result)
result = divide(15, 3)
fmt.Println("result is", result)
result = divide(15, 0)
fmt.Println("result is", result)
}程序运行结果:
result is 5
result is 5
捕获到panic: chu shu bu neng wei 0!
recover 的重要注意事项
| 注意事项 | 说明 |
|---|---|
必须放在 defer 中 |
recover() 只有在 defer 函数中调用才有效,直接调用会返回 nil。 |
| 只能捕获当前 goroutine 的 panic | 如果一个 panic 发生在另一个 goroutine 中,需要在那 goroutine 内部用 defer 捕获。 |
recover 返回的是 interface{} |
所以通常用 if r := recover(); r != nil 来判断,并可以把 r 断言成具体类型来处理。 |

