go依賴注入管理工具wire的使用方法
wire能做什么?
wire是一個依賴注入管理的工具。主要包含兩個角色provider,injector,
- provider: a function that can produce a value.
- injector: a fucntion that calls providers in dependency order.
我們通過簡單電子商務網站的例子來看看wire能干什么。假設有個購物車(ShoppingCart)的對象,該對象由多個產品列表(ProductList)組成,他們的UML關系如下
具體代碼實現如下,
type ShoppingCart struct { // 依賴于產品列表 ProductList *ProductList // 其他屬性和方法 } // 產品列表模塊 type ProductList struct { // 一些產品數據和方法 } // 創(chuàng)建購物車的函數, 這就是依賴注入 // ShoppingCart對象,需要的部分組件,來自于入參,而不是函數內部構建 func NewShoppingCart(pl *ProductList) (*ShoppingCart, error) { return &ShoppingCart{ProductList: pl}, nil } // 創(chuàng)建產品列表的函數 func NewProductList() (*ProductList, error) { return &ProductList{}, nil }
在不使用wire的情況下,如果我們需要使用ShoppingCart
對象,需要下面這樣一段初始化代碼:
func InitializeShoppingCart() (*ShoppingCart, error) { // 1. 首先構建productList productList, err := NewProductList() if err != nil { return nil, err } // 2. 構建ShoppingCart shoppingCart, err := NewShoppingCart(productList) if err != nil { return nil, err } return shoppingCart, nil }
這個例子只涉及到兩個對象,所以這段代碼寫起來不費力氣。如果這是一個復雜的WebServer
對象呢?我們初始化較多的對象,比如redisDao,MySQLDao,Kafka,Log,httpServer,grpcServer
等等,這些依賴關系都需要我們自己處理,那得多麻煩啊。所以,wire就是解決這個問題的,你可以理解wire幫我們寫了類似于InitializeShoppingCart 這個函數。 下面,我們來看看如何使用wire?
wire如何解放雙手?
我們知道wire中有兩個概念,一個是provider,一個是injector,在上面例子中,
- provider:是
NewShoppingCart, NewProductList
這兩個函數
他們有一個共同點是,都創(chuàng)建一個對象?,F在我們需要創(chuàng)建一個指令,告訴wire如何根據這些provider,寫出InitializaShoppingCart
這個函數。我們想想,如果wire是一個人,你該如何告訴他寫這個函數呢?
- 告訴他,這個函數,最終創(chuàng)建的對象是什么?也就是
return
是什么?【注,也有一些人這樣寫,傳入的是指針,函數中所有的操作,就是初始化這個指針中的內容】 - 需要有哪些provider,能夠創(chuàng)建最終的對象?
明白這兩點,我們新建一個wire.go
的文件,并在開始處寫上+build wireinjector
。接著,寫上這樣一段代碼:
func InitializeShoppingCart() (*ShoppingCart, error) { wire.Build( NewShoppingCart, NewProductList, ) return nil, nil }
然后,在文件所在目錄,執(zhí)行wire
。這個時候,會出現一個wire_gen.go
的文件。
func InitializeShoppingCart() (*ShoppingCart, error) { productList, err := NewProductList() if err != nil { return nil, err } shoppingCart, err := NewShoppingCart(productList) if err != nil { return nil, err } return shoppingCart, nil }
wire生成的代碼,和我們自己寫的是一樣的。相比于處理復雜的對象依賴關系,寫一個injector
要簡單的多。關于wire的使用,還是有一些坑的,下面我們看看如何避開這些坑。
注意事項
坑一:創(chuàng)建同一個對象,只需要一個provider,不要創(chuàng)建多個provider。
set has multiple bindings for go-tool/basic/wire1.Fooer
當injector中,有多個provider生成同一個對象時,會報上述錯誤。
坑二:當使用接口時,保證上provider生成的是接口,后一個provider使用的也是接口,同時保證1對1關系;
坑三:如果一個provider生成的是接口實現的結構體,另外一個是provider的入參是接口,這個時候,需要顯式的使用wire.Bind
函數告訴接口的具體實現者。
var set = wire.NewSet(NewFooerImp, NewSecond, wire.Bind(new(Fooer), new(*MyFooer)))
坑四:提供的Provider需要剛剛好,不要多,也不要少;
- inject InitializeEvent: unused provider "NewEventNumber: 有沒有使用過的provider;
- inject InitializeEvent: no provider found for Greet: 沒有provider;
以上就是go依賴注入管理工具wire的使用方法的詳細內容,更多關于go wire管理依賴的資料請關注腳本之家其它相關文章!
相關文章
關于golang 字符串 int uint int64 uint64&
這篇文章主要介紹了golang 字符串 int uint int64 uint64 互轉,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-01-01