panic是程序崩溃信号,非错误处理手段;仅用于无法继续执行的致命场景,如初始化失败、配置缺失、断言崩溃;自动触发场景包括切片/数组/字符串越界、空指针解引用、整数除零、类型断言失败、向已关闭channel发送数据。

panic 不是错误处理手段,而是程序崩溃信号;它只该用于无法继续执行的致命场景,比如初始化失败、配置缺失、断言崩溃——别用它替代 error 返回。
哪些操作会自动触发 panic
Go 运行时会在检测到不可恢复的非法状态时自动调用 panic,你没写 panic() 也会发生:
-
arr[10]访问长度为 5 的切片或数组 —— 报index out of range [10] with length 5 -
*nilPtr解引用未初始化的指针 —— 报invalid memory address or nil pointer dereference -
str[100]超出字符串长度访问 —— 报string index out of range -
10 / 0整数除零 —— 报integer divide by zero -
interface{}(val).(int)类型断言失败(如把string强转int)—— 报interface conversion: string is not int - 向已关闭的
chan发送数据:ch 后 <code>close(ch)再发 —— 报send on closed channel -
close(nilChan)关闭 nil channel —— 报close of nil channel
手动调用 panic() 的正确姿势
仅在程序已无法维持基本运行前提时使用,例如关键配置缺失、依赖服务不可达、内部不变量被破坏:
- 参数必须是
interface{},常用string或自定义 error 类型,如panic("config file not found") - 不要在循环里、HTTP handler 主逻辑中、或可预期的用户输入校验处用
panic—— 这些该返回error - 启动阶段检查失败可 panic,比如
if db == nil { panic("failed to initialize database") } - panic 后当前函数立即终止,但已注册的
defer仍会执行(这是做清理的最后机会)
recover 必须在 defer 中且仅对当前 goroutine 有效
recover() 不是万能 catch,它有硬性约束:
立即学习“go语言免费学习笔记(深入)”;
- 只能在
defer函数体内调用,写在普通代码块里返回nil - 只捕获**同一 goroutine** 中发生的 panic;其他 goroutine 的 panic 它看不见
- recover 后程序从 defer 所在函数的**下一行继续执行**,不是回滚到 panic 那行
- 典型模式:
defer func() { if r := recover(); r != nil { log.Printf("panic: %v", r) } }() - Web 服务中常在 handler 入口加 recover,防止单个请求 panic 导致整个 server 崩溃
最容易被忽略的一点:recover 捕获后,panic 携带的值类型仍是原始类型(比如 string 或 error),若直接打印 r 可能 panic 自身(比如 r 是 nil 接口),务必先做类型断言或判空。另外,goroutine 泄漏、资源未释放等问题不会因 recover 而自动修复——它只救流程,不救状态。


















