recover
👉 recover
— cơ chế “chống cháy” khi panic
.
recover
— cơ chế “chống cháy” khi panic
.🔥 1. recover
là gì?
recover
là gì?recover()
là builtin function của Go dùng để phục hồi lại chương trình từ panic
.
Nhưng chỉ hoạt động bên trong một
defer
function.
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
⚙️ 2. Cách hoạt động
Khi một panic
xảy ra:
Go bắt đầu unwind call stack.
Mọi
defer
được thực thi theo thứ tự LIFO.Nếu trong bất kỳ
defer
nào gọirecover()
— thì panic sẽ dừng lại, chương trình tiếp tục chạy bình thường.
✅ 3. Ví dụ đơn giản
func safeDivide(a, b int) {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered:", r)
}
}()
fmt.Println(a / b) // panic nếu b = 0
}
func main() {
safeDivide(10, 0)
fmt.Println("Program continues...")
}
Output:
Recovered: runtime error: integer divide by zero
Program continues...
🔄 4. Kết hợp panic
+ recover
+ defer
panic
+ recover
+ defer
func mustInit() {
defer func() {
if err := recover(); err != nil {
log.Println("Init failed:", err)
}
}()
panic("DB not found")
}
Đây là cách "safe startup" thường dùng trong app backend.
🧱 5. Use case phổ biến của recover
recover
✅ a. Middleware HTTP — chống crash toàn server
func RecoveryMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
log.Printf("Recovered: %v", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}()
next.ServeHTTP(w, r)
})
}
Dùng để đảm bảo nếu có panic trong bất kỳ handler nào, server không crash.
✅ b. Job runner / worker pool
func worker(job func()) {
defer func() {
if err := recover(); err != nil {
log.Println("Recovered job panic:", err)
}
}()
job()
}
Bảo vệ worker khi xử lý task bất ổn.
❌ 6. Cảnh báo quan trọng
Recover bên ngoài defer
Không hoạt động
Lạm dụng recover để ẩn lỗi
Làm mất trace gây khó debug
Không log lỗi
Bạn recover rồi “nuốt luôn lỗi” => khó trace production bug
✅ Best Practices của recover
recover
Protect HTTP server
Viết middleware có defer
+recover
Protect goroutines
Bọc goroutine bằng wrapper recover
Logging error
Luôn log rõ panic + stack trace
Không dùng trong business logic
Không recover rồi tiếp tục xử lý logic sai
🧠 Bonus: Ghi lại stack trace khi recover
defer func() {
if r := recover(); r != nil {
log.Printf("panic: %v\n%s", r, debug.Stack())
}
}()
Thêm
runtime/debug
để in call stack giúp debug sâu.
🔚 Tổng kết
panic
Ném lỗi nghiêm trọng
defer
Đảm bảo cleanup chạy cuối
recover
Cứu chương trình khỏi crash
Last updated