golang panic和recover使用

  • 时间:2025-11-19 19:40 作者: 来源: 阅读:0
  • 扫一扫,手机访问
摘要:在 Go 语言中,panic 和 recover 是用于处理程序中严重错误的机制,它们不是常规的错误处理方式(应使用 error 返回值),而是用于处理那些本不应该发生、或程序无法继续正常执行的异常情况。1. panicpanic 是 Go 提供的一个内置函数,用于主动触发一个运行时恐慌(panic),导致程序停止当前函数的执行,并开始**向上回溯(unwind)**调用栈。触发 panic 的情

在 Go 语言中,panic 和 recover 是用于处理程序中严重错误的机制,它们不是常规的错误处理方式(应使用 error 返回值),而是用于处理那些本不应该发生、或程序无法继续正常执行的异常情况。

1. panic

panic 是 Go 提供的一个内置函数,用于主动触发一个运行时恐慌(panic),导致程序停止当前函数的执行,并开始**向上回溯(unwind)**调用栈。

触发 panic 的情况:

  • 显式调用 panic("something went wrong")
  • 运行时错误,例如:
  • 数组/切片越界
  • 类型断言失败(非安全版本)
  • 向 nil 的 map 写入
  • 除以零(仅在整数时 panic,浮点数返回 +Inf)

panic 的行为:

  • 当 panic 被调用时,当前函数停止执行。
  • 所有通过 defer 声明的函数会按后进先出(LIFO)顺序执行
  • 然后 panic 会向上传播到调用栈的上一层函数,同样执行其 defer,直到程序崩溃或被 recover 捕获。

示例:

package main

import "fmt"

func badFunction() {
    panic("oh no! something terrible happened")
    fmt.Println("This will not be printed")
}

func main() {
    fmt.Println("Start")
    badFunction()
    fmt.Println("End") // 不会执行
}

输出:

Start
panic: oh no! something terrible happened
goroutine 1 [running]:
main.badFunction()
...
main.main()
...

2. recover

recover 是一个内置函数,用于捕获 panic 并恢复正常执行。它只能在 defer 函数中有效。

关键点:

  • recover() 只有在 defer 函数中调用才有效。
  • 如果当前 goroutine 正在 panic,recover() 会返回传给 panic 的值(一般是 string 或 error)。
  • 如果没有 panic,recover() 返回 nil。
  • 一旦 recover 成功捕获 panic,程序将继续执行 defer 函数之后的代码,不会继续 panic 向上传播

示例:使用 recover 捕获 panic

package main

import "fmt"

func safeDivide(a, b int) int {
    defer func() {
       if r := recover(); r != nil {
          fmt.Println("Recovered from panic:", r)
       }
    }()

    if b == 0 {
       panic("division by zero")
    }
    return a / b
}

func main() {
    fmt.Println("Start")
    result := safeDivide(10, 0)    // 触发 panic,但被 recover 捕获
    fmt.Println("Result:", result) // 会执行,result 为 0(未赋值)
    fmt.Println("End")
}

输出:

Start
Recovered from panic: division by zero
Result: 0
End

3. panic 和 recover 的典型使用场景

虽然 Go 鼓励使用 error 作为主要错误处理方式,但 panic/recover 在以下场景中是合理的:

  • 不可恢复的错误:如配置文件缺失、关键依赖未初始化等。
  • 库函数的防御性检查:防止调用者传入非法参数导致后续崩溃。
  • Web 框架中的全局错误处理:捕获 handler 中的 panic,返回 500 错误,避免服务器崩溃。
  • 初始化失败:init() 函数中无法返回 error,可用 panic。

4. 注意事项与最佳实践

  • 不要滥用 panic:普通错误应返回 error。
  • ✅ recover 只在 defer 中有效。
  • ✅ recover 捕获后,程序从 defer 结束后继续,原函数的返回值需手动处理(可能为零值)。
  • ❌ 不要用 panic/recover 做控制流(如取代 if/else)。
  • ✅ 在 defer 中使用匿名函数来包裹 recover 是常见模式。

总结

特性

panic

recover

作用

触发异常,中断执行

捕获 panic,恢复执行

调用位置

任意地方

只能在 defer 函数中

返回值

interface{},一般是错误信息

是否必须

否(但用于防止程序崩溃)

推荐用途

不可恢复错误、程序逻辑错误

全局错误处理、保护关键函数

记住:Go 的哲学是“显式错误处理”,优先使用 if err != nil,panic/recover 是最后的手段。

  • 全部评论(0)
手机二维码手机访问领取大礼包
返回顶部