使用google wire解決依賴注入
google wire是golang的一個依賴注入解決的工具,這個工具能夠自動生成類的依賴關係。
當我們寫程式碼的時候,都希望,類都是一個個獨立的結構,互不耦合,而類之間的關係,是通過外部傳遞不同的依賴元件,來組裝出來,生成不同的例項。
一個耦合的例子:
type BOB struct {
db *sql.DB
}
func NewBOB() *BOB{
return &BOB{
db: new(MysqlDB),
}
}
在例子中,BOB類會來依賴db類,而db類的生成,是通過new(MysqlDB)生成的,這樣就把BOB和db類耦合起來了,如果要改變其他的資料庫類,則需要改動BOB的程式碼了,這樣是不合理的,因為BOB依賴的是DB,而不是MysqlDB,最好的方式,MysqlDB類改動了,但BOB程式碼不用改。
下面改一下程式碼,一個組裝依賴的例子:
type BOB struct {
db *sql.DB
}
func NewBOB(db *sql.DB) *BOB{
return &BOB{
db: db,
}
}
func main(){
db := new(MysqlDB)
NewBOB(db)
}
在上面的例子裡,原來的new(MysqlDB),替換為db: db,通過引數的方式來初始化db了,而類的組裝是在main函式裡面實現,使用這樣組裝,當MysqlDB改為XXDB的時候,BOB的程式碼不用變動,程式碼不用變動,出問題的機率就會少,這樣的組裝方式,就叫依賴注入了。
一般情況下,組裝類的依賴關係,都可以手寫,但平時寫專案的時候,類的數量,很容易會有幾十個,這個時候,如果手寫的話,會很囉嗦麻煩,而且要理順好生成的順序。
為了解決依賴組裝的問題,golang有uber的dig和Facebook的inject,這兩個都是通過執行時注入的,使用執行時注入,會有一些問題,比如不好除錯,錯誤提示不及時等,而wire採用不同的方式來實現,通過生成依賴注入的程式碼來解決問題,這樣就和手寫是一樣的,只是減輕手寫的麻煩。
wire可以通過類組裝,結構體組裝,還可以引數和異常返回,看看例子:
type Foo struct {
}
func NewFoo() *Foo{
return &Foo{}
}
type Bar struct {
foo *Foo
}
func NewBar(foo *Foo) *Bar {
return &Bar{
foo:foo,
}
}
func (p *Bar) Test(){
fmt.Println("hello")
}
wire.go:
package wire
import (
wire "github.com/google/wire"
)
type Instance struct {
Foo *Foo
Bar *Bar
}
var SuperSet = wire.NewSet(NewFoo, NewBar)
func InitializeAllInstance() *Instance {
wire.Build(SuperSet, Instance{})
return &Instance{}
}
執行wire命令,會讀取到wire.NewSet裡面的ProviderSet,通過分析各個函式的引數和返回值,來自行解決依賴,可以生成wire_gen.go:
func InitializeAllInstance() *Instance {
foo := NewFoo()
bar := NewBar(foo)
instance := &Instance{
Foo: foo,
Bar: bar,
}
return instance
}
總結
通過google wire能夠讓手寫依賴關係變得簡單,而且相當直觀,值得推薦使用。
[參考資料]