Go语言通过error和panic/recover处理错误,recover需在defer中调用以捕获panic,防止程序崩溃。在HTTP中间件和goroutine中需单独设置recover,结合日志与监控实现高可用与可观测性。

Go语言中没有传统的异常机制,而是通过 error 和 panic/recover 机制来处理错误和程序异常。为了防止服务因未处理的 panic 而崩溃,合理使用 recover 是构建高可用服务的关键。
当程序发生严重错误(如数组越界、空指针解引用)或主动调用 panic 时,Go 会中断当前流程并开始栈展开,执行 defer 函数。如果 defer 中调用 recover,可以捕获 panic 值并恢复正常执行,从而避免程序退出。
recover 只能在 defer 调用的函数中生效,直接调用无效。典型用法如下:
func safeHandler() {
defer func() {
if r := recover(); r != nil {
log.Printf("Recovered from panic: %v", r)
}
}()
// 可能触发 panic 的代码
panic("something went wrong")
}
Web 服务中,单个请求处理函数的 panic 会导致整个服务中断。通过中间件统一 recover 可防止崩溃。
立即学习“go语言免费学习笔记(深入)”;
以 net/http 为例,编写 recover 中间件:
func recoverMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
defer func() {
if r := recover(); r != nil {
log.Printf("Panic recovered: %v\nStack trace: %s", r, debug.Stack())
http.Error(w, "Internal Server Error", 500)
}
}()
next(w, r)
}
}
// 使用
http.HandleFunc("/api", recoverMiddleware(myHandler))
在 Gin、Echo 等框架中也有内置或可自定义的 recover 中间件,建议开启并配合日志记录。
主 goroutine 的 panic 可被 recover 捕获,但子 goroutine 中的 panic 不会影响主流程,也不会被外层 recover 捕获。必须在每个子 goroutine 内部 defer recover。
常见模式:
go func() {
defer func() {
if r := recover(); r != nil {
log.Printf("Goroutine panic recovered: %v", r)
}
}()
// 业务逻辑
}()
对于通过 go 关键字启动的协程,遗漏 recover 将导致 panic 无法捕获,可能造成服务静默退出或资源泄漏。
recover 的目的不是隐藏问题,而是防止服务崩溃的同时记录现场。建议:
示例:
log.Printf("Panic: %v\nStack:\n%s", r, debug.Stack())
基本上就这些。关键是在关键入口(如 HTTP 处理器、goroutine 起点)设置 defer recover,配合日志和监控,做到服务不崩溃、问题可追溯。不复杂但容易忽略细节。
以上就是Golang错误恢复机制 防止服务崩溃方案的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号