如何使用Golang recover捕获panic_防止程序崩溃并处理异常
技术百科
P粉602998670
发布时间:2026-01-01
浏览: 次 Go语言用panic/recover+defer实现异常处理,recover仅在defer函数中有效且限于当前goroutine;需在易错逻辑外层封装safeRun等模式,子goroutine须独立加recover;recover后不继续执行panic点,仅恢复调度并返回。
Go语言中没有传统意义上的try-catch机制,而是通过panic和recover配合defer来实现运行时异常的捕获与恢复。关键在于:recover只能在defer函数中调用才有效,且仅能捕获当前goroutine中的panic。
recover必须配合defer使用
recover不是全局拦截器,它只在defer延迟执行的函数中调用时
才起作用。如果写在普通逻辑里,返回值始终为nil,无法捕获任何panic。
- 正确写法:在可能panic的函数内,先用
defer注册一个匿名或命名函数,在其中调用recover() - 错误写法:把
recover()放在if判断里、或者放在panic之后但不在defer中
典型安全封装模式
常见做法是将易出错逻辑包裹进一个带recover的闭包,统一处理异常:
func safeRun(f func()) {
defer func() {
if r := recover(); r != nil {
log.Printf("panic recovered: %v", r)
// 可记录日志、上报监控、返回默认值等
}
}()
f()
}
调用方式:safeRun(func() { riskyOperation() })。这样即使riskyOperation触发panic,程序也不会退出,而是继续执行后续逻辑。
注意goroutine隔离性
每个goroutine有独立的panic/recover作用域。主goroutine中defer的recover无法捕获子goroutine里的panic。
- 子goroutine需自行加defer+recover,例如启动时就包装:
go func() { defer safeRecover(); doWork() }() - HTTP服务中,标准
http.ServeMux已内置recover(如net/http包),但自定义handler仍建议手动加一层防护
recover后不能“继续执行”panic发生点
recover的作用是让程序从panic状态恢复正常调度,但它不会回到panic发生的那行代码继续执行。控制权会回到defer所在函数的末尾,然后按正常流程返回。
- 例如:函数A中defer了recover,A内部某处panic → 执行defer函数 → recover成功 → A函数直接返回,不执行panic之后的代码
- 因此,recover适合做“兜底清理”和“错误转化”,不适合用来“重试”或“修正错误后续跑完”
# go语言
# go
# golang
# if
# red
# 封装
# 作用域
# try
# catch
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- Win11鼠标灵敏度怎么调 Win11鼠标指针移动
- php中::能访问全局变量吗_全局作用域与类作用域
- Python多进程教程_multiprocessi
- PHP主流架构怎么集成Redis缓存_配置步骤【方
- Windows10如何更改桌面图标间距_Win10
- Go 语言标准库为何不提供泛型 Contains
- c++中如何对数组进行排序_c++数组排序算法汇总
- Python装饰器复用技巧_通用能力解析【教程】
- PHP怎么接收URL中的锚点参数_获取#后面参数值
- XML的“混合内容”是什么 怎么用DTD或XSD定
- 如何用列表一次性对 DataFrame 的指定列应
- 如何快速验证Golang安装是否成功_运行go v
- Win10系统怎么查看端口状态_Windows10
- Mac怎么给文件夹加密_Mac创建加密磁盘映像教程
- php8.4如何配置ssl证书_php8.4htt
- 如何使用Golang包导出规则_控制函数和变量可见
- Python技术债务管理_长期维护解析【教程】
- Win11怎么关闭透明效果_Windows11个性
- 如何使用Golang实现聊天室消息存档_存储聊天记
- 短链接怎么用php还原_从基础原理到代码实现教学【
- Win11怎么恢复旧版开始菜单_通过软件还原Win
- Python网页解析流程_html结构说明【指导】
- Python文件管理规范_工程实践说明【指导】
- Win11怎么查看wifi信号强度_检测Windo
- Win11时间怎么同步到原子钟 Win11高精度时
- c++中如何使用虚函数实现多态_c++多态性实现原
- 如何在Golang中写入XML文件_生成符合规范的
- Win11怎么设置鼠标宏_Win11鼠标按键自定义
- 如何用正则与预处理结合精准拦截拼接式垃圾域名
- 如何在Golang中处理通道发送接收错误_防止阻塞
- Ajax提交表单PHP怎么接收_处理Ajax发送的
- Win11怎么更改任务栏位置_修改注册表将Win1
- Win11怎么设置快速访问主页_Windows11
- 如何在 Go 中可靠地测试含 time.Time
- 如何使用Golang实现跨域请求支持_Golang
- 如何使用Golang table-driven f
- c++20的std::format怎么用 比pri
- 短链接还原php提示内存不足_调整PHP内存限制设
- php8.4新语法match怎么用_php8.4m
- Win11系统更新后黑屏怎么办 Win11更新黑屏
- Win11怎么解压RAR文件 Win11自带解压功
- Win11如何开启telnet服务 Win11启用
- Win11怎么清理C盘OneDrive缓存_Win
- Mac的访达(Finder)怎么用_Mac文件管理
- Python对象比较与排序_集合使用说明【指导】
- c++中的Tag Dispatching是什么_c
- Django 测试数据库表缺失与字段未创建问题的完
- MAC怎么使用表情符号面板_MAC Emoji快捷
- 如何在 Go 中正确测试带 Cookie 的 HT
- 如何使用Golang benchmark测量函数延

QQ客服