Singleton trong Dix
Tổng quan
Trong Dix, Singleton là cách khai báo dependency theo wrapper type ở tham số hàm, dùng kiểu:
di.Singleton[T]
Mục tiêu của wrapper này là giúp bạn biểu diễn rõ ràng dependency cần được truyền theo ngữ nghĩa singleton trong graph.
Cấu trúc Singleton[T]
Trong package di, cấu trúc hiện tại là:
type Singleton[T any] struct {
Instance T
}Khởi tạo wrapper:
s := di.NewSingleton(value)Trong đó value có kiểu T.
Cách unwrap để lấy giá trị
Bạn có 2 cách lấy lại giá trị bên trong wrapper:
- Dùng method
Get()(khuyến nghị) - Truy cập trực tiếp field
Instance
Ví dụ:
func UseRepo(repoS di.Singleton[*Repo]) {
repo1 := repoS.Get() // cach khuyen nghi
repo2 := repoS.Instance // cach truc tiep
_, _ = repo1, repo2
}Khuyến nghị dùng Get() để code nhất quán và dễ thay đổi implementation sau này.
Quy tắc khai báo
- Chỉ dùng đúng dạng
di.Singleton[T]. - Không dùng con trỏ wrapper:
*di.Singleton[T]là không hợp lệ. Tphải khớp với provider trả về trong graph.
Ví dụ đúng
package app
import "github.com/smtdfc/dix/di"
type Repo struct{}
type App struct{}
// @Injectable
func NewRepo() *Repo {
return &Repo{}
}
// @Injectable
// @Root
func NewApp(repo di.Singleton[*Repo]) *App {
_ = repo
return &App{}
}Ví dụ sai
package app
import "github.com/smtdfc/dix/di"
type Repo struct{}
type App struct{}
// @Injectable
func NewRepo() *Repo {
return &Repo{}
}
// @Injectable
// @Root
func NewApp(repo *di.Singleton[*Repo]) *App {
return &App{}
}Lỗi parser tương ứng:
parser/validation: singleton dependency must be di.Singleton[T], not *di.Singleton[T]
Hành vi generate code
Khi gặp singleton dependency, Dix sẽ tạo object mới và bọc trực tiếp bằng di.NewSingleton(...) tại call-site.
Ví dụ dạng generate:
repo0 := pkg.NewRepo()
app0 := pkg.NewApp(di.NewSingleton(pkg.NewRepo()))Điểm cần lưu ý:
- Dependency thường: lấy từ container scope đã generate.
- Dependency singleton: bọc trực tiếp bằng
di.NewSingleton(...)khi truyền vào provider cần singleton.
Nếu cần unwrap ngay trong provider, bạn có thể làm như sau:
func NewApp(repoS di.Singleton[*Repo]) *App {
repo := repoS.Get()
_ = repo
return &App{}
}Lỗi thường gặp
Xem danh sách lỗi và cách khắc phục tại: Lỗi thường gặp.