使用google wire解決依賴注入

小魂師發表於2019-02-12

使用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能夠讓手寫依賴關係變得簡單,而且相當直觀,值得推薦使用。

[參考資料]

相關文章