Trong lập trình Go, bạn có thể đã từng gặp tình huống muốn truyền một biến cấu hình (config), hoặc đối tượng kết nối CSDL (database), vào một hàm nhưng không thể làm trực tiếp vì hàm đó cần đúng một định dạng.
Giải pháp? Closure kết hợp với Dependency Injection.
Bài viết này sẽ giúp bạn hiểu rõ cách sử dụng kỹ thuật này bằng ví dụ đơn giản, dễ hiểu, không gắn với bất kỳ framework nào.
🎯 Vấn đề thường gặp
func Greet(name string) {
fmt.Println("Hello", name)
}
Bây giờ bạn muốn thêm một cấu hình prefix để tùy biến lời chào, ví dụ: "👋 Xin chào" hoặc "Hello".
Bạn không muốn viết lại logic mỗi lần, mà muốn truyền prefix từ bên ngoài. Nhưng Greet() lại chỉ chấp nhận name.
🛠 Cách dùng Closure để truyền thêm biến
Bước 1: Tạo Closure có chứa prefix
func MakeGreeter(prefix string) func(name string) {
return func(name string) {
fmt.Printf("%s %s\n", prefix, name)
}
}
Bước 2: Sử dụng Closure như một hàm thông thường
func main() {
greeter := MakeGreeter("👋 Xin chào")
greeter("Nguyễn Văn A")
another := MakeGreeter("Hello")
another("John")
}
Kết quả:
👋 Xin chào Nguyễn Văn A Hello John
📌 Giải thích
MakeGreeterlà một hàm tạo ra một hàm khác (closure).- Closure có thể “nhớ” giá trị
prefixkhi nó được tạo. - Logic xử lý vẫn giống nhau, nhưng dễ tái sử dụng với các cấu hình khác nhau.
🌐 Ứng dụng thực tế với HTTP Server
func NewHelloHandler(greeting string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
name := r.URL.Query().Get("name")
fmt.Fprintf(w, "%s %s", greeting, name)
}
}
func main() {
http.HandleFunc("/hello", NewHelloHandler("Xin chào"))
log.Fatal(http.ListenAndServe(":8080", nil))
}
Khi người dùng truy cập: http://localhost:8080/hello?name=Nam ⇒ Kết quả:
Xin chào Nam
🔚 Kết luận
Closure trong Go không chỉ là một tính năng của ngôn ngữ — nó là công cụ mạnh mẽ để bạn quản lý phụ thuộc linh hoạt mà vẫn giữ cho mã gọn gàng, dễ mở rộng.
Bạn hoàn toàn có thể áp dụng kỹ thuật này vào bất kỳ chức năng nào như cấu hình, logger, dịch vụ kết nối cơ sở dữ liệu, hoặc handler trong web API.
Nếu bạn muốn xem thêm ví dụ chuyên sâu hơn (gắn với database, bot, hay context), hãy để lại bình luận nhé!