golang 每日一庫之依賴注入庫 samber-do
do
是 Go 語言中一個輕量級的依賴注入(Dependency Injection, DI)容器,由 samber 開發。它基於 Go 1.18+ 泛型實現,爲 Go 提供了一個類型安全的 DI 方案。
do
庫的設計理念是簡化服務組件之間的依賴管理,取代手工創建依賴關係的繁瑣工作,使不同組件之間鬆散耦合、更易測試與維護。
與反射型 DI 框架不同,do
在註冊和解析依賴時不使用反射,因此性能開銷很小。
功能簡介
-
服務註冊
:使用
do.Provide
系列函數將服務構造函數註冊到容器中(默認懶加載,即按需單例創建);也可以使用ProvideTransient
註冊每次調用都新建實例的工廠(瞬時模式);或使用ProvideValue
/ProvideNamedValue
註冊已經創建好的實例(急加載)。註冊時可指定名稱或匿名服務(推薦匿名,由框架自動命名)。 -
依賴解析
:通過
do.Invoke[T](injector)
或do.MustInvoke[T](injector)
獲取指定類型的服務實例。容器會自動根據函數簽名的參數解析依賴,並以依賴圖的方式按順序實例化各服務(默認單例)。服務加載順序爲調用順序(先調用的服務會優先初始化)。 -
生命週期管理
:
do
支持生命週期鉤子。服務只要實現特定接口,就會被框架在適當時機調用。比如實現do.Healthcheckable
接口的服務可以通過do.HealthCheck[T](injector)
或injector.HealthCheck()
進行健康檢查;實現do.Shutdownable
接口的服務會在容器關閉時被回調,以便釋放資源。容器關閉時會按照服務註冊的 反初始化順序(後註冊的先關閉)依次調用這些Shutdown
方法。 -
其它特性
:支持服務命名、覆蓋(
Override*
)和組合(do.Package
),可以複製容器(injector.Clone()
),並提供工具函數列出已註冊或已實例化的服務列表。整個庫非常輕量,無外部依賴,也無需生成代碼。
參考示例
下面給出一個簡單示例,演示如何使用 do
完成依賴注入。假設有兩個服務 Engine
和 Car
,其中 Car
依賴於 Engine
:
type Engine struct {
Started bool
}
// 構造函數:創建 Engine 實例
func NewEngine(i do.Injector) (*Engine, error) {
return &Engine{Started: false}, nil
}
type Car struct {
Engine *Engine
}
// 構造函數:創建 Car 實例時自動注入 Engine
func NewCar(i do.Injector) (*Car, error) {
engine := do.MustInvoke[*Engine](i) // 從容器中獲取 Engine
return &Car{Engine: engine}, nil
}
func (c *Car) Start() {
c.Engine.Started = true
println("Car is running")
}
在 main
函數中創建容器、註冊服務並調用:
func main() {
injector := do.New() // 創建依賴注入容器
do.Provide(injector, NewEngine) // 註冊 Engine 服務(懶加載單例)
do.Provide(injector, NewCar) // 註冊 Car 服務,依賴 Engine
// 獲取 Car 實例(會自動創建 Car 及其依賴 Engine)
car := do.MustInvoke[*Car](injector)
car.Start() // 使用服務
injector.Shutdown() // 關閉容器,按註冊順序倒序調用可選的 Shutdown 鉤子
}
以上代碼中,調用 do.Provide
將構造函數註冊到容器,do.MustInvoke[*Car]
會觸發容器根據依賴關係創建對象並返回。運行後會輸出 "Car is running"
。如果服務實現了 Shutdown()
方法(實現 do.Shutdownable
),容器在調用 injector.Shutdown()
時也會自動調用它完成清理。
優勢有哪些
使用 do
庫相比手動通過 new
或自己維護全局變量的方式,有以下優勢:
-
松耦合與易測試
:通過容器集中管理依賴關係,組件之間無需硬編碼調用構造函數,降低耦合度,更易替換和模擬測試。依賴關係一目瞭然,也方便單元測試時注入假組件。
-
類型安全
:
do
完全基於 Go 泛型和靜態類型檢查,不使用反射,不會產生運行時類型錯誤。編譯期就能發現依賴缺失或類型不匹配的問題,避免了很多隱蔽錯誤。 -
代碼簡潔
:簡化了大量樣板代碼,只需通過構造函數和少量註冊代碼,框架就自動解決依賴,減少手工傳參和變量管理的工作,提高開發效率。
-
生命週期管理
:容器能統一處理啓動、健康檢查、優雅停機等流程,無需在業務代碼中編寫額外邏輯,適合需要集中管理服務生命週期的應用場景。
-
輕量無依賴
:
do
自身很輕量,沒有外部依賴和代碼生成工具,運行時開銷低,適合小型服務、命令行工具、微服務等多種場景。
對於有多個互相依賴組件、希望簡化啓動與測試流程的項目,do
是一個友好的選擇。
標題:golang 每日一庫之依賴注入庫 samber/do
作者:mooncakeee
地址:http://blog.dd95828.com/articles/2025/05/09/1746754797718.html
聯繫:scotttu@163.com
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/H2uic0Ws9bgztXzSslAYcA