答案:panic和recover是Go中用于处理严重运行时错误的机制,panic触发后沿调用栈冒泡并执行defer函数,recover仅在defer中调用时可捕获panic并恢复执行。它们适用于程序无法继续的极端情况,如初始化失败或不可恢复的内部错误,但不应替代常规错误处理。在多goroutine中,recover只能捕获当前goroutine的panic,因此常在goroutine入口使用defer-recover防止服务整体崩溃。常见陷阱包括recover不在defer中调用、defer内再次panic或捕获后不记录日志,最佳实践是记录堆栈信息、在服务入口统一防护并避免在库中使用panic。

Golang中的
panic
recover
panic
defer
recover
recover
panic
而
recover
defer
panic
panic
recover
panic
recover
defer
举个例子,一个经典的用法是包裹可能出错的代码块:
立即学习“go语言免费学习笔记(深入)”;
package main
import (
"fmt"
"runtime/debug"
)
func mightPanic() {
// 模拟一个可能导致panic的操作,比如空指针解引用
var s *string
fmt.Println(*s) // 这一行会引发panic
fmt.Println("这行代码不会被执行")
}
func main() {
fmt.Println("程序开始运行...")
// 使用defer和recover来捕获mightPanic中的异常
defer func() {
if r := recover(); r != nil {
fmt.Printf("啊哈!程序发生了一个panic:%v\n", r)
// 打印堆栈信息,这对于调试非常有用
fmt.Printf("堆栈信息:\n%s\n", debug.Stack())
fmt.Println("但我们成功捕获并恢复了!")
}
}()
mightPanic() // 调用可能panic的函数
fmt.Println("程序继续执行,即使mightPanic发生了问题。")
fmt.Println("程序结束。")
}运行这段代码,你会看到尽管
mightPanic
panic
main
defer
recover
panic
坦白说,我在实际开发中,对
panic
recover
什么时候用呢?
panic
panic
panic
panic
defer-recover
我个人非常不建议将
panic
error
panic
panic
panic
if err != nil
在我看来,
panic
std::terminate
System.exit()
recover
panic
这是
panic
recover
recover
panic
这意味着,如果一个goroutine发生了
panic
panic
defer-recover
panic
考虑以下场景:
package main
import (
"fmt"
"time"
)
func worker() {
defer func() {
if r := recover(); r != nil {
fmt.Printf("Worker goroutine捕获到panic:%v\n", r)
}
}()
fmt.Println("Worker goroutine开始工作...")
time.Sleep(1 * time.Second)
panic("Worker goroutine遭遇致命错误!") // worker goroutine内部panic
fmt.Println("Worker goroutine工作完成(这行不会执行)")
}
func main() {
fmt.Println("主goroutine开始运行...")
// 启动一个worker goroutine
go worker()
// 主goroutine继续做自己的事情
time.Sleep(3 * time.Second)
fmt.Println("主goroutine运行结束。")
}在这个例子中,
worker
panic
defer-recover
worker
time.Sleep
worker
defer-recover
worker
然而,有一种情况需要特别注意:如果一个panic
所以,在启动新的goroutine时,为了服务的稳定性,一个常见的最佳实践是在每个独立的goroutine的入口处都放置一个
defer-recover
panic
func safeGo(f func()) {
go func() {
defer func() {
if r := recover(); r != nil {
fmt.Printf("一个goroutine发生panic并被捕获:%v\n", r)
// 这里通常还会记录详细的日志,包括堆栈信息
}
}()
f()
}()
}
// 在其他地方使用
// safeGo(func() {
// // 你的goroutine逻辑
// // 可能会panic的代码
// })这种模式可以有效地隔离
panic
在使用
panic
recover
常见陷阱:
recover
defer
recover()
defer
defer
recover()
nil
panic
// 错误示例
func badRecover() {
// 这不会捕获任何panic
if r := recover(); r != nil {
fmt.Println("不会执行到这里")
}
panic("oops")
}defer
panic
defer
panic
panic
panic
defer
panic
recover
panic
panic
error
panic
defer-recover
defer
defer
defer
defer
最佳实践:
panic
recover
panic
panic
runtime/debug.Stack()
defer func() {
if r := recover(); r != nil {
log.Printf("CRITICAL: Panic occurred: %v\nStack trace:\n%s", r, debug.Stack())
// 可以在这里发送警报,或者执行其他紧急清理
}
}()defer-recover
defer-recover
panic
panic
interface{}panic
panic
error
recover
panic
panic
panic
panic
总的来说,
panic
recover
以上就是Golangpanic恢复机制 recover捕获异常的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号