Defer
📘 1. defer
là gì?
defer
là gì?defer
trong Go dùng để trì hoãn thực thi một hàm cho đến khi hàm hiện tại kết thúc (return, panic, hoặc exit).
Nói cách khác:
defer
giống như “cleanup hook” — nó sẽ chạy cuối cùng, bất kể bạn thoát hàm kiểu gì.
🔧 2. Cách dùng cơ bản
func main() {
defer fmt.Println("Defer run at the end")
fmt.Println("Main function start")
}
🧾 Output:
Main function start
Defer run at the end
⛓️ 3. Thứ tự thực thi (LIFO)
Các defer được stack lại và chạy theo thứ tự Last In First Out (LIFO).
func main() {
defer fmt.Println("first")
defer fmt.Println("second")
defer fmt.Println("third")
}
🧾 Output:
third
second
first
📌 4. Use cases thường gặp
✅ a. Đóng tài nguyên
file, err := os.Open("data.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
Không cần nhớ phải close cuối hàm — cực kỳ sạch & an toàn.
✅ b. Lock / Unlock
mu.Lock()
defer mu.Unlock()
Tránh quên
Unlock()
— giúp goroutine không bị deadlock.
✅ c. Transaction / Rollback
tx := db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
panic(r)
} else {
tx.Commit()
}
}()
Kết hợp với
recover
để rollback nếu panic.
✅ d. Timing / Logging
start := time.Now()
defer func() {
log.Printf("done in %s", time.Since(start))
}()
⚠️ 5. Lưu ý quan trọng
⚠️ a. Tham số được đánh giá ngay lập tức
func main() {
x := 10
defer fmt.Println(x) // ✅ in ra 10
x = 20
}
Biến
x
được chụp ngay lúc defer được gọi.
⚠️ b. defer
ảnh hưởng đến hiệu năng nếu lặp quá nhiều
defer
ảnh hưởng đến hiệu năng nếu lặp quá nhiềuDù rất tiện lợi, nhưng defer tạo một stack nên:
for i := 0; i < 1_000_000; i++ {
defer func() {}() // ❌ tốn nhiều RAM & chậm
}
Tránh defer trong tight loop nếu performance quan trọng.
✅ Ưu điểm của defer
defer
Rõ ràng, sạch code
Đảm bảo cleanup được gọi ở đúng chỗ
Giảm lỗi logic
Tránh quên đóng tài nguyên
Hữu ích khi panic
Vẫn chạy dù bị panic
❌ Nhược điểm của defer
defer
Hiệu năng thấp hơn gọi trực tiếp
Vì lưu lại stack defer
Dễ hiểu nhầm thứ tự
Khi dùng nhiều defer lồng nhau
Không reset được thứ tự
Không thể thay đổi LIFO order
🧠 Best Practices (theo Senior Dev)
Mở file, DB, net.Conn
defer Close()
ngay sau khi mở
Lock
defer Unlock()
ngay sau Lock()
Nhiều cleanup liên tục
Tách hàm, không nhồi nhiều defer
Panic recovery
Kết hợp defer
+ recover
để rollback, log
Last updated