Go依賴注入工具wire的具體使用
Go相對(duì)java和C++是較新的語言,但也有諸多優(yōu)秀特性及生態(tài)庫。本文介紹大多數(shù)軟件工程中常用的功能:依賴注入。首先介紹什么是依賴注入,go實(shí)現(xiàn)庫wire與其他語言的差異。然后通過簡(jiǎn)單示例實(shí)現(xiàn)依賴注入,簡(jiǎn)化代碼、提升可讀性。
依賴注入
依賴注入是一種對(duì)象接收它所依賴的其他對(duì)象(稱為依賴項(xiàng))的技術(shù)。通常,接收對(duì)象稱為客戶端,傳入(“注入”)對(duì)象稱為服務(wù)。
為了更好理解,下面通過一個(gè)簡(jiǎn)單示例進(jìn)行說明:
package main import ( ? ?"fmt" ) type Message string type Greeter struct { ? ?Message Message } type Event struct { ? ?Greeter Greeter } func GetMessage() Message { ? ?return Message("Hello world!") } func GetGreeter(m Message) Greeter { ? ?return Greeter{Message: m} } func (g Greeter) Greet() Message { ? ?return g.Message } func GetEvent(g Greeter) Event { ? ?return Event{Greeter: g} } func (e Event) Start() { ? ?msg := e.Greeter.Greet() ? ?fmt.Println(msg) } func main() { ? ?message := GetMessage() ? ?greeter := GetGreeter(message) ? ?event := GetEvent(greeter) ? ?event.Start() }
上面代碼有message, greeter, event;GetMessage函數(shù)返回消息,GetGreeter函數(shù)接受消息返回greeter,getEvent函數(shù)接受返回greeter返回事件。事件還有一個(gè)方法start輸出消息。
在main函數(shù)中,首先創(chuàng)建消息,然后作為依賴傳入greeter,最后傳給事件。運(yùn)行程序可以看到輸出“Hello world!",這是相對(duì)較淺的依賴圖,但也能看到其復(fù)雜性,這也是依賴注入庫wire的價(jià)值體現(xiàn)。
Wire簡(jiǎn)介
Wire是代碼依賴工具,它沒有采用反射機(jī)制或運(yùn)行時(shí)狀態(tài),使用Wire可以有效避免手動(dòng)編寫硬代碼依賴。Wire在編譯時(shí)生成源碼,官方文檔描述: “In Wire, dependencies between components are represented as function parameters, encouraging explicit initialization instead of global variables.” (在Wire中組件之間的依賴關(guān)系表示為函數(shù)參數(shù),優(yōu)先采用顯式初始化而不是全局變量。)
通過下面命令安裝wire:go get github.com/google/wire/cmd/wire
;全局安裝wire,為后續(xù)使用wire命令生成代碼:go install github.com/google/wire/cmd/wire
下面我們使用Wire作為依賴注入工具重構(gòu)上面代碼,新增wire.go文件,增加下面代碼:
//go:build wireinject // +build wireinject package main import "github.com/google/wire" func InitializeEvent() Event { ? ?wire.Build(GetMessage, GetGreeter, GetEvent) ? ?return Event{} }
首先導(dǎo)入wire,然后創(chuàng)建InitializeEvent函數(shù),該返回在main函數(shù)中調(diào)用的事件。函數(shù)體內(nèi)調(diào)用wire,在構(gòu)建器方法內(nèi)傳入所有依賴,注意,傳入依賴與順序無關(guān)。然后返回空事件,無需擔(dān)心,所有交給Wire。
注意,文件上面的注釋告訴Go在編譯時(shí)忽略該文件,要確保該注釋行后面增加一行空行。
下面是main函數(shù)代碼:
func main() { event := InitializeEvent() event.Start() }
現(xiàn)在成功地把main函數(shù)代碼降為兩行。在wire.go代碼目錄下,執(zhí)行wire命令,wire會(huì)生成wire_gen.go文件:
// Code generated by Wire. DO NOT EDIT. //go:generate go run github.com/google/wire/cmd/wire //go:build !wireinject // +build !wireinject package main // Injectors from wire.go: func InitializeEvent() Event { ?? ?message := GetMessage() ?? ?greeter := GetGreeter(message) ?? ?event := GetEvent(greeter) ?? ?return event }
同樣生成的文件上面注釋與wire.go文件相比多了!,表示wire在編譯時(shí)忽略,go編譯時(shí)啟動(dòng)。這是運(yùn)行main函數(shù)正確輸出結(jié)果。
帶參數(shù)依賴
如果需要?jiǎng)討B(tài)傳入消息作為參數(shù)呢?下面我們修改GetMessage函數(shù):
func GetMessage(text string) Message { return Message(text) }
再次運(yùn)行wire命令,可以看到wire_gen.go 代碼也有相應(yīng)修改:
// Code generated by Wire. DO NOT EDIT. //go:generate go run github.com/google/wire/cmd/wire //go:build !wireinject // +build !wireinject package main // Injectors from wire.go: func InitializeEvent(text string) Event { ?? ?message := GetMessage(text) ?? ?greeter := GetGreeter(message) ?? ?event := GetEvent(greeter) ?? ?return event }
現(xiàn)在修改main.go代碼:
func main() { event := InitializeEvent("Hello Golang") event.Start() }
運(yùn)行結(jié)果與期望一致。
如果修改wire.go代碼, 模擬缺少部分依賴:
func InitializeEvent(text string) Event { wire.Build(GetMessage, GetEvent) return Event{} }
執(zhí)行wire命令,會(huì)正確提示少了相應(yīng)的依賴:
inject InitializeEvent: no provider found for demo01.Greeter needed by demo01.Event in provider "GetEvent"
總結(jié)
本文介紹了基本wire概念,并通過簡(jiǎn)單示例介紹動(dòng)態(tài)實(shí)現(xiàn)依賴注入。但一般wire會(huì)在較大項(xiàng)目使用,更多高級(jí)功能參考官方文檔:https://github.com/google/wire/blob/main/docs/guide.md#advanced-features 。
到此這篇關(guān)于Go依賴注入工具wire的文章就介紹到這了,更多相關(guān)Go依賴注入工具wire內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go實(shí)現(xiàn)簡(jiǎn)易R(shí)PC框架的方法步驟
本文旨在講述 RPC 框架設(shè)計(jì)中的幾個(gè)核心問題及其解決方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-03-03Go語言實(shí)現(xiàn)MapReduce的示例代碼
MapReduce是一種備受歡迎的編程模型,它最初由Google開發(fā),用于并行處理大規(guī)模數(shù)據(jù)以提取有價(jià)值的信息,本文將使用GO語言實(shí)現(xiàn)一個(gè)簡(jiǎn)單的MapReduce,需要的可以參考下2023-10-10Golang中切片長(zhǎng)度和容量的區(qū)別示例詳解
切片長(zhǎng)度與容量在Go中很常見,切片長(zhǎng)度是切片中可用元素的數(shù)量,而切片容量是從切片中第一個(gè)元素開始計(jì)算的底層數(shù)組中的元素?cái)?shù)量,這篇文章主要給大家介紹了關(guān)于Golang中切片長(zhǎng)度和容量區(qū)別的相關(guān)資料,需要的朋友可以參考下2024-01-01淺析go中的map數(shù)據(jù)結(jié)構(gòu)字典
golang中的map是一種數(shù)據(jù)類型,將鍵與值綁定到一起,底層是用哈希表實(shí)現(xiàn)的,可以快速的通過鍵找到對(duì)應(yīng)的值。這篇文章主要介紹了go中的數(shù)據(jù)結(jié)構(gòu)字典-map,需要的朋友可以參考下2019-11-11Golang基礎(chǔ)教程之字符串string實(shí)例詳解
這篇文章主要給大家介紹了關(guān)于Golang基礎(chǔ)教程之字符串string的相關(guān)資料,需要的朋友可以參考下2022-07-07Go語言題解LeetCode1260二維網(wǎng)格遷移示例詳解
這篇文章主要為大家介紹了Go語言題解LeetCode1260二維網(wǎng)格遷移示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01golang進(jìn)行簡(jiǎn)單權(quán)限認(rèn)證的實(shí)現(xiàn)
本文主要介紹了golang簡(jiǎn)單權(quán)限認(rèn)證的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09