Lesson 19 — Error Handling kiểu Go

Go không có try/catch. Mọi lỗi là một giá trị trả về mà bạn phải xử lý tường minh. 3 module dưới đây cho phép bạn (1) so sánh trực tiếp luồng exception của Java với luồng error-return của Go, (2) tự build wrap chain rồi xem errors.Is traverse qua chain như thế nào, (3) xem stack unwind khi panic được recover bắt trong defer.

1. Module 1 — Error vs Exception

Cùng một bài toán: hàm readConfig gọi openFile, file không tồn tại. Bên trái là cách Java unwind stack qua exception. Bên phải là cách Go return error tường minh ở từng tầng. Bấm ▶ Step hoặc ⏵ Play để chạy animation đồng bộ 2 phía.

🟠 Java — exception

Call stack
main()
readConfig()
openFile("a.txt")
Trace
Bấm Step/Play để bắt đầu.

🔵 Go — error value

Call stack
main()
readConfig()
openFile("a.txt")
Trace
Bấm Step/Play để bắt đầu.
Quan sát chính:
  • Java: Khi exception ném ra, JVM tự động unwind stack đến khi gặp catch. Code intermediate (readConfig) không biết exception đi qua.
  • Go: Mỗi tầng tường minh return err. readConfig chủ động wrap thêm context bằng fmt.Errorf("... %w", err). Caller đọc code thấy ngay điểm có lỗi.

2. Module 2 — Wrap chain inspector

Tự build wrap chain 3 tầng: chọn error gốc, viết format string cho 2 tầng wrap. Sau đó nhập target để xem errors.Is(err, target) traverse qua chain ra sao.

Cách đọc: nút trên cùng là err ngoài cùng (gần caller). Mũi tên ↓ Unwrap đi xuống tầng sâu hơn. Khi bấm Run, từng node sẽ sáng vàng (đang check), node match target sẽ chuyển xanh. Đổi verb từ %w sang %v để thấy chain bị đứt — errors.Is không xuyên qua được nữa.

3. Module 3 — Panic + recover demo

Hàm safeCall gọi doWork, doWork deref nil pointer → panic. safeCalldefer chứa recover() → bắt panic, trả về như error bình thường, process KHÔNG crash.



  
Call stack (đáy ↓ đỉnh)
Narration
Bấm Step/Play để chạy.
Final return
Quy tắc: recover() CHỈ hoạt động trong defer. Khi panic xảy ra, runtime unwind stack ngược; gặp deferrecover non-nil thì panic dừng. Use case duy nhất nên dùng: HTTP middleware để 1 request bug không kill cả server.
⚠ Đừng dùng recover khắp nơi. Recover giấu bug. Chỉ recover ở biên (HTTP handler, worker goroutine ngoài cùng) và PHẢI log + stack trace.