Go Context: Cách Cancel Request Đang Chạy Một Cách Graceful
Go Context: Cách Cancel Request Đang Chạy Một Cách Graceful
Hôm nay mình muốn nói về một pattern cực kỳ hay trong Go mà mình hay dùng khi build backend services: context.Context để cancel request.
Hồi mình mới code Go, hay gặp trường hợp API call lâu, user bấm cancel hoặc timeout, nhưng goroutine bên dưới vẫn chạy tiếp, tốn resource và gây memory leak. Sau khi dùng context thì mọi thứ sạch sẽ hơn rất nhiều.
Ảnh: ThisIsEngineering — Pexels
Cách dùng cơ bản:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
resp, err := client.Do(req)
Trong handler, mình hay propagate context xuống database query, cache, hoặc external API calls. Khi context bị cancel (timeout hoặc user cancel), tất cả downstream operations đều dừng lại graceful.
Đặc biệt hữu ích khi build microservices với nhiều layer. Mình từng fix một bug production nơi worker queue vẫn chạy task cũ sau khi request timeout, dẫn đến data inconsistency. Dùng context.WithCancel + select pattern đã giải quyết triệt để.
Ảnh: Kevin Ku — Pexels
Pattern này kết hợp với context.WithValue để pass request ID hoặc trace info cũng rất mạnh. Go context không chỉ là cancel, nó là cách để control lifecycle của request một cách rõ ràng.
Nếu bạn đang viết service bằng Go, context là thứ nên master đầu tiên. Nó giúp code robust hơn, dễ debug hơn, và tránh nhiều bug khó chịu.
📋 Phụ lục thuật ngữ
- Context — Interface trong Go dùng để quản lý lifecycle, deadline, cancellation signal
- WithTimeout — Tạo context có thời hạn tự động cancel sau khoảng thời gian nhất định
- WithCancel — Tạo context kèm function để cancel thủ công
Bạn hay dùng context như thế nào trong project Go của mình? Có pattern nào hay ho không? Mình đang muốn học thêm đây.