Singleton
Kiến thức nền tảng
Tình huống sử dụng thực tế
Cách implement chuẩn production (thread-safe, lazy, với DI)
Anti-pattern cần tránh
Benchmark và kiểm thử đơn vị
💡 1. Khi nào cần dùng Singleton?
✅ Dùng khi:
Chỉ cần một instance duy nhất trong toàn app (vd: config, logger, db connection pool)
Tránh khởi tạo lại đối tượng nặng hoặc tốn chi phí (vd: Redis pool, Kafka producer)
Đảm bảo thread-safe access trong concurrent Golang apps
❌ Không dùng khi:
Mỗi request cần state riêng biệt
Muốn dễ test unit (singleton khó mock nếu không inject được)
🧱 2. Các cách implement Singleton trong Go
⚙️ Cách 1: Thread-safe với sync.Once (chuẩn production)
sync.Once (chuẩn production)🧠 Giải thích:
sync.Onceđảm bảo hàmDochỉ được chạy 1 lần, dù nhiều goroutine cùng gọiThread-safe tuyệt đối, không cần lock thủ công
Lazy-init: chỉ khởi tạo khi lần đầu được gọi
🧪 3. Test đơn vị singleton
🔥 4. Tình huống thực tế
🧩 Use Case: Logger Service
Sử dụng:
🧨 5. Anti-pattern cần tránh
❌ Dùng init() để khởi tạo Singleton:
init() để khởi tạo Singleton:Khởi tạo eager (luôn khởi tạo kể cả không dùng)
Không thread-safe nếu init phức tạp
Khó test/mock trong unit test
🔧 6. Singleton với Dependency Injection (Pro)
Kỹ thuật: inject singleton vào service layer
Tại main.go:
➡️ Điều này giúp dễ mock db trong unit test thay vì hardcoded singleton trong UserService.
📈 7. Benchmark sơ bộ
Với sync.Once, chi phí truy xuất sau lần đầu là cực thấp (vài ns), không cần tối ưu thêm.
✅ Tổng kết checklist
Dùng sync.Once để đảm bảo thread-safe lazy init
✅
Không khởi tạo trước bằng init()
✅
Inject singleton vào services để dễ test
✅
Tránh lưu state bên trong singleton (nếu có concurrency)
✅
Viết test để kiểm tra instance
✅
Last updated