答案:defer确保函数退出前执行指定代码,recover用于捕获panic并恢复执行。二者结合可在发生panic时记录日志、释放资源,防止程序崩溃,常用于HTTP中间件、goroutine保护等场景,但不应替代常规error处理。

在Golang中,
defer
recover
panic
defer
recover
defer
panic
理解
defer
recover
defer
return
panic
defer
recover
defer
panic
panic
panic
recover
nil
一个典型的使用模式是,在一个可能引发
panic
defer
recover
panic
package main
import (
"fmt"
"log"
"runtime/debug" // 用于获取堆栈信息
)
func mightPanic(input int) {
if input == 0 {
panic("输入不能为0!") // 模拟一个运行时错误
}
fmt.Printf("处理输入: %d\n", input)
}
func safeCall(input int) (err error) {
defer func() {
if r := recover(); r != nil {
log.Printf("捕获到panic: %v\n", r)
debug.PrintStack() // 打印完整的堆栈信息
err = fmt.Errorf("操作失败: %v", r) // 将panic转换为error返回
}
}()
mightPanic(input) // 调用可能panic的函数
fmt.Println("safeCall函数正常结束。")
return nil
}
func main() {
fmt.Println("--- 第一次调用 (正常情况) ---")
if err := safeCall(10); err != nil {
fmt.Printf("主函数收到错误: %v\n", err)
}
fmt.Println("\n--- 第二次调用 (会panic的情况) ---")
if err := safeCall(0); err != nil {
fmt.Printf("主函数收到错误: %v\n", err)
}
fmt.Println("\n程序继续执行...")
}在这个例子中,
safeCall
defer
mightPanic
mightPanic(0)
panic
defer
recover()
panic
panic
error
立即学习“go语言免费学习笔记(深入)”;
这个问题常常困扰初学者,因为在很多语言里,异常(Exception)是处理错误的通用机制。但在Go里,设计哲学是明确区分两种情况:可预期的错误(Error)和不可预期的异常(Panic)。
首先,Go语言鼓励使用
error
error
而
panic
panic
defer
recover
recover
panic
error
defer
recover
panic
panic
总结一下,
error
panic
recover
defer
recover
一个非常典型的场景是在服务级别的请求处理边界。想象一下,你有一个HTTP服务,每个进来的请求都会在一个独立的goroutine中处理。如果某个请求的处理逻辑因为某种原因(比如数据格式错误导致空指针,或者某个依赖服务返回了意料之外的响应导致逻辑崩溃)引发了
panic
recover
panic
在这种情况下,通常会在HTTP处理函数的入口处,或者更常见的,在HTTP中间件中设置一个
defer
recover
panic
// 示例:HTTP中间件中的panic恢复
func PanicRecoveryMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if r := recover(); r != nil {
log.Printf("HTTP请求处理中发生panic: %v\n", r)
debug.PrintStack() // 打印堆栈信息
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}()
next.ServeHTTP(w, r)
})
}另一个重要场景是保护独立的goroutine。在Go中,一个goroutine的
panic
panic
defer
recover
panic
// 示例:保护后台goroutine
func runWorker() {
defer func() {
if r := recover(); r != nil {
log.Printf("工作goroutine发生panic: %v\n", r)
debug.PrintStack()
// 可以在这里重启worker,或者发送通知
}
}()
// 模拟可能发生panic的工作
for i := 0; i < 5; i++ {
if i == 3 {
panic("工作过程中出现严重错误!")
}
fmt.Printf("工作goroutine: 正在处理 %d\n", i)
time.Sleep(time.Second)
}
}
// func main() {
// go runWorker()
// // 主goroutine继续做其他事情
// time.Sleep(10 * time.Second)
// fmt.Println("主程序结束。")
// }此外,
defer
error
panic
defer
recover
panic
总的来说,
defer
recover
error
尽管
defer
recover
首先,一个非常重要的点是recover
defer
defer
recover()
nil
panic
recover
panic
defer
func badRecover() {
// 这样做是无效的,recover()会返回nil
if r := recover(); r != nil {
fmt.Println("尝试恢复,但无效:", r)
}
panic("这是一个panic") // 这个panic会直接导致程序崩溃
}
// 应该这样:
func goodRecover() {
defer func() {
if r := recover(); r != nil {
fmt.Println("成功恢复:", r)
}
}()
panic("这是一个panic")
}其次,recover
panic
panic
recover
defer
recover
panic
func parentFunc() {
defer func() {
if r := recover(); r != nil {
fmt.Println("父goroutine捕获到panic:", r) // 这个recover捕获不到子goroutine的panic
}
}()
go func() { // 启动一个子goroutine
// 子goroutine没有自己的recover,这里的panic会导致整个程序崩溃
panic("子goroutine中的panic!")
}()
time.Sleep(2 * time.Second) // 等待子goroutine执行
fmt.Println("父goroutine正常结束。")
}再者,切忌滥用panic
recover
error
error
panic
panic
panic
defer
另外,在recover
panic
recover
defer
panic
panic
runtime/debug.PrintStack()
最后,要考虑到panic
recover
error
panic
panic
panic
recover
总之,
defer
recover
以上就是如何通过defer和recover在Golang中捕获并处理panic的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号