Package context cung cấp cơ chế truyền deadline, tín hiệu hủy (cancellation), và các giá trị request-scoped xuyên suốt chuỗi goroutine.
Nguyên tắc quan trọng: luôn truyền context như tham số đầu tiên của function, không bao giờ lưu context vào struct.
go
// WithTimeout — tự động hủy sau timeout
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel() // luôn gọi cancel để tránh leak
resp, err := http.NewRequestWithContext(ctx, "GET", url, nil)
// WithCancel — hủy thủ công
ctx, cancel := context.WithCancel(context.Background())
go func() {
time.Sleep(2 * time.Second)
cancel() // hủy khi không cần kết quả nữa
}()
// Truyền context vào database query
rows, err := db.QueryContext(ctx, "SELECT * FROM users")
// HTTP server — mỗi request mang context riêng
func handler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context() // tự hủy khi client ngắt kết nối
result, err := db.QueryContext(ctx, "SELECT ...")
_ = result
_ = err
}The context package propagates deadlines, cancellation signals, and request-scoped values across goroutines.
Key rule: always pass context as the first function parameter; never store it in a struct.
go
// WithTimeout — auto-cancels after the deadline
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel() // always call cancel to avoid goroutine leaks
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
// WithCancel — manual cancellation
ctx, cancel := context.WithCancel(context.Background())
go func() {
time.Sleep(2 * time.Second)
cancel() // cancel when result is no longer needed
}()
// Pass context to a database query
rows, err := db.QueryContext(ctx, "SELECT * FROM users")
// HTTP server — each request has its own context
func handler(w http.ResponseWriter, r *http.Request) {
ctx := r.Context() // auto-cancelled when client disconnects
result, err := db.QueryContext(ctx, "SELECT ...")
_ = result
_ = err
}