go也能依賴注入?進來細說
需要依賴注入時,Go有什么實現方案?本文詳細介紹了使用google/wire庫實現依賴注入的方法。
google/wire 是 Go 語言的編譯時依賴注入框架,與 Spring IoC 一樣,wire 的目的也是讓開發者從對項目中大量依賴的創建和管理中解脫出來,但兩者在實現方式上有著很大的不同。
Go 中的依賴注入
在 Go 中,我們通常采取在構造函數中傳入依賴的方式創建對象:
這在小規模項目中效果很好,但當項目規模變大時,單個對象的創建往往需要多個依賴,而這些依賴通常還有它自己的依賴,這就導致對象的創建變得繁瑣,容易出錯。
wire 如何完成依賴注入
在開發中,我們創建對象的過程可以分為兩步:
- 定義結構體的構造函數
2.調用結構體的構造函數進行實例化
第一步我們聲明了構造結構體需要的依賴,而 wire 做的,就是?幫我們“寫”好第二步的代碼。
依賴聲明
為了生成第二步中的代碼,我們首先需要將所有的構造函數(準確的說是所有需要注入的依賴)進行聲明并傳遞給?wire.Build?方法:
setup?函數的內容最終會被 wire 用下面的實現替換(接下來會進行說明):
可以看到上面 wire 為我們“寫”好的代碼其實跟我們自己將會寫的代碼是一樣的,可以很容易的讀懂。但隨著依賴增多,這樣的代碼就會增加,想象一下,如果項目中有上百個依賴,那么就會有上百行的 New…(…), if err != nil {…}?代碼。
使用 go generate 生成依賴注入代碼
wire 就是做了這樣一件事:幫我們生成所有需要的對象創建代碼,開發時我們只需要在結構體的構造函數中聲明自己需要什么。
wire 在實際項目中的使用步驟:
- 通過?wire.Bind?方法進行依賴聲明,假設這部分代碼放在?inject.go?文件中
- 使用 go generate http://c.biancheng.net/view/4442.html 命令生成代碼
go generate?需要通過?//go:generate?注釋的方式使用,創建?wire_gen.go?文件并添加該注釋:
- 在項目目錄下執行 go generate 命令。
運行該命令時,它將掃描與當前包相關的源代碼文件,找出所有包含?//go:generate 的特殊注釋,提取并執行該特殊注釋后面的命令。
至此,你就可以看到 wire_gen.go 里已經生成好 func setup(ctx context.Context) (sv *server.Server, clean func(), err error)?方法,方法體為依賴注入(對象創建)代碼。
- 最后一步,在 main 方法中調用?setup?方法(這里假設我們的項目是一個提供 RESTful 接口的 HTTP 服務)
需要注意的是,如果 inject.go 和 wire_gen.go 在同一個 package 下,那此時 IDE 會提示語法錯誤,因為兩個文件下存在方法簽名一樣的兩個方法。此時可以使用 //+build go build 構建約束對其中一個文件進行排除。
首先在?inject.go?中加入如下的構建標簽:
然后在 wire_gen.go 中加入構建約束使 go build 時排除帶 wireinject 標簽的文件:
使用 wire.Bind, wire.Value 等方法聲明和組織依賴
wire 在 go generate 掃描代碼時從 wire.Bind 中提取項目依賴關系并為我們生成依賴注入代碼,那我們要怎樣將依賴關系更高效,清晰的“告知”給 wire 呢?
wire 提供了幾個函數幫助我們組織和聲明項目中的依賴關系:
- wire.Bind: 將接口和其實現進行綁定
- wire.Value: 將值(實例)包裝為依賴
原文:https://mp.weixin.qq.com/s/plzFgg7nUthKMMgh56e-TA