成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

為什么把 Dig 遷移到 Wire

開發(fā) 開發(fā)工具
dig和wire都是Go依賴注入的工具,那么,本質(zhì)上功能相似的工具,為什么要從dig切換成 wire?

[[409705]]

本文轉(zhuǎn)載自微信公眾號(hào)「吳親強(qiáng)的深夜食堂」,作者吳親庫里。轉(zhuǎn)載本文請(qǐng)聯(lián)系吳親強(qiáng)的深夜食堂公眾號(hào)。

dig和wire都是Go依賴注入的工具,那么,本質(zhì)上功能相似的工具,為什么要從dig切換成 wire?

場(chǎng)景

我們從場(chǎng)景出發(fā)。假設(shè)我們的項(xiàng)目分層是:

router->controller->service->dao。

目錄大概就長(zhǎng)這樣:

現(xiàn)在我們需要對(duì)外暴露一個(gè)訂單服務(wù)的接口。

首頁看main.go文件。

這里使用了gin啟動(dòng)項(xiàng)目。

dig

然后我們查看dig.ContainerByDig(),

通過dig.New()創(chuàng)建一個(gè)di容器。Provide函數(shù)用于添加服務(wù)提供者,Provide函數(shù)第一個(gè)參數(shù)本質(zhì)上是個(gè)函數(shù)。一個(gè)告訴容器 "我能提供什么,為了提供它,我需要什么?" 的函數(shù)。

我們看上面的server.NewOrderServer,

這里的NewOrderServer(xxx)在Provide中的語意就是 "我能提供一個(gè)OrderServerInterface服務(wù),但是我需要依賴一個(gè)dao.OrderDao"。

剛才的代碼中,

因?yàn)槲覀兊恼{(diào)用鏈?zhǔn)莄ontroller->server->dao,那么本質(zhì)上他們的依賴是controller<-server<-dao,只是依賴的不是具體的實(shí)現(xiàn),而是抽象的接口。

所以你看到Provide是按照依賴關(guān)系順序?qū)懙摹?/p>

其實(shí)完全沒有必要,因?yàn)檫@一步dig只會(huì)對(duì)這些函數(shù)進(jìn)行分析,提取函數(shù)的形參以及返回值。然后根據(jù)返回的參數(shù)來組織容器結(jié)構(gòu)。并不會(huì)在這一步執(zhí)行傳入的函數(shù),所以在Provide階段前后順序并不重要,只要確保不遺漏依賴項(xiàng)即可。

萬事俱備,我們開始注冊(cè)一個(gè)能獲取訂單的路由,

此時(shí),調(diào)用invoke, 才是真正需要獲取*controller.OrderHandler對(duì)象。

調(diào)用invoke方法,會(huì)對(duì)傳入的參數(shù)做分析,參數(shù)中存在handle *controller.OrderHandler,就會(huì)去容器中尋找哪個(gè)Provide進(jìn)來的函數(shù)返回類型是handle *controller.OrderHandler,

然后對(duì)應(yīng)找到,

發(fā)現(xiàn)這個(gè)函數(shù)有形參server.OrderServerInterface,那就去找對(duì)應(yīng)返回此類型的函數(shù),

又發(fā)現(xiàn)形參(order dao.OrderDao),

最后發(fā)現(xiàn)NewOrderDao沒有依賴,不需要再查詢依賴。

開始執(zhí)行函數(shù)的調(diào)用NewOrderDao(),把返回的OrderDao

傳入到上層的NewOrderServer(order dao.OrderDao)進(jìn)行函數(shù)調(diào)用,

NewOrderServer(order dao.OrderDao)返回的

OrderServerInterface繼續(xù)返回到上層

NewOrderHandler(server server.OrderServerInterface)

執(zhí)行調(diào)用,最后再把函數(shù)調(diào)用返回的*OrderHandler傳遞給

dig.Invoke(func(handle *controller.OrderHandler) {},

整個(gè)鏈路就通了。上面看的可能不太舒服,用一個(gè)圖來描述這個(gè)過程。

dig的整個(gè)流程采用的是反射機(jī)制,在運(yùn)行時(shí)計(jì)算依賴關(guān)系,構(gòu)造依賴對(duì)象。

這樣會(huì)存在什么問題?

假設(shè)我現(xiàn)在注釋掉Provide的一行代碼,比如,

我們?cè)诰幾g項(xiàng)目的時(shí)候并不會(huì)報(bào)任何錯(cuò)誤,只會(huì)在運(yùn)行時(shí)才發(fā)現(xiàn)缺少了依賴項(xiàng)。

wire

還是上面的代碼,我們使用wire作為我們的DI容器。

wire也有兩個(gè)核心概念:Provider和Injector。

其中Provider的概念和dig的概念是一樣的:"我能提供什么?我需要什么依賴"。

比如下面wire.go中的代碼,

dao.NewOrderDaoserver.NewOrderServer以及controller.NewOrderHandler就是Provider。

你會(huì)發(fā)現(xiàn)這里還調(diào)用wire.NewSet把他們整合在一起,賦值給了一個(gè)變量orderSet。

其實(shí)是用到ProviderSet的概念。原理就是把一組相關(guān)的Provider進(jìn)行打包。

這樣的好處是:

  • 結(jié)構(gòu)依賴清晰,便于閱讀。
  • 以組的形式,減少injector里的Build。

至于injector,本質(zhì)上就是按照依賴關(guān)系調(diào)用Provider的函數(shù),然后最終生成我們想要的對(duì)象(服務(wù))。

比如上面的ContainerByWire()就是一個(gè)injector。

那么wire.go文件整體的思路就是:定義好injector,然后實(shí)現(xiàn)所需的Provider。

最后在當(dāng)前wire.go文件夾下執(zhí)行wire命令后,

此時(shí)如果你的依賴項(xiàng)存在問題,那么就會(huì)報(bào)錯(cuò)提示。比如我現(xiàn)在隱藏上面的dao.NewOrderDao,那么會(huì)出現(xiàn) ,

如果依賴不存在問題,最終會(huì)生成一個(gè)wire_gen.go文件。

需要注意上面兩個(gè)文件。我們看到wire.go中第一行//+build wireinject,這個(gè)build tag確保在常規(guī)編譯時(shí)忽略wire.go文件。

而與之相對(duì)的wire_gen.go中的//+build !wireinject。

兩個(gè)對(duì)立的build tag是為了確保在任意情況下,兩個(gè)文件只有一個(gè)文件生效, 避免出現(xiàn) "ContainerByWire()方法被重新定義" 的編譯錯(cuò)誤。

現(xiàn)在我們可以真正使用injector了,我們?cè)谌肟谖募刑鎿Q成dig。

一切正常。

當(dāng)然wire有一個(gè)點(diǎn)需要注意,在wire.go文件中開頭幾行:

build tag和package他們之間是有空行的,如果沒有空行,build tag識(shí)別不了,那么編譯的時(shí)候就會(huì)報(bào)重復(fù)聲明的錯(cuò)誤:

還有很多高級(jí)的操作可以自行了解。如果有需要完整代碼請(qǐng)下方留言。

總結(jié)

以上大體介紹了 go 中dig和wire兩個(gè)DI工具。其中dig是通過運(yùn)行時(shí)反射實(shí)現(xiàn)的依賴注入。 而wire是根據(jù)自定義的代碼,通過命令,生成相應(yīng)的依賴注入代碼,在編譯期就完成依賴注入,無需反射機(jī)制。 這樣的好處是:

  • 方便排查,如果存在依賴錯(cuò)誤,編譯時(shí)就能發(fā)現(xiàn)。而 dig 只能在運(yùn)行時(shí)才能發(fā)現(xiàn)依賴錯(cuò)誤。
  • 避免依賴膨脹,wire生成的代碼只包含被依賴的,而dig可能會(huì)存在好多無用依賴。
  • 依賴關(guān)系靜態(tài)存在源碼,便于工具分析。

Reference

[1]https://github.com/google/wire

[2]https://github.com/uber-go/dig

[3]https://medium.com/@dche423/master-wire-cn-d57de86caa1b

[4]https://www.cnblogs.com/li-peng/p/14708132.html

 

責(zé)任編輯:武曉燕 來源: 吳親強(qiáng)的深夜食堂
相關(guān)推薦

2021-01-25 07:40:37

Druid數(shù)據(jù)eBay

2020-04-20 08:08:23

MongoDBElasticsear數(shù)據(jù)庫

2020-09-09 09:38:47

GoLangNodeJS編程語言

2020-10-13 09:25:27

ESClickHouse搜索引擎

2020-03-12 08:00:34

MySQL遷移TiDB

2020-01-18 09:35:03

微服務(wù)團(tuán)隊(duì)架構(gòu)

2020-09-16 14:56:11

MYSQL知識(shí)數(shù)據(jù)庫

2009-08-06 09:20:30

2022-03-19 16:47:47

WordPress網(wǎng)站遷移服務(wù)器

2009-06-16 15:15:18

WebLogic EJ

2017-08-31 17:43:06

云端遷移云計(jì)算

2021-04-22 15:55:56

UCaaS統(tǒng)一通信企業(yè)通信

2011-04-18 09:36:50

微軟Azure云平臺(tái)

2019-06-13 18:18:29

零售商云端遷移

2018-07-05 14:24:48

ECM云計(jì)算SaaS

2021-12-06 13:45:49

云計(jì)算云計(jì)算環(huán)境數(shù)據(jù)中心

2023-10-19 16:39:38

2018-07-04 14:17:10

微服務(wù)代碼開發(fā)

2023-07-07 08:02:48

TypeScript編譯器文檔

2018-11-15 16:18:14

微服務(wù)架構(gòu)拆分服務(wù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日韩国产一区二区三区 | 波多野结衣一区二区 | 天天躁日日躁狠狠躁2018小说 | 久久精品视频在线观看 | 日韩成人免费av | 精品欧美久久 | 可以看黄的视频 | 在线观看国产精品一区二区 | 国产精品久久精品 | 新疆少妇videos高潮 | 国产精品久久久久久吹潮 | 亚洲视频一区二区三区 | 国产亚洲精品区 | 成人无遮挡毛片免费看 | 国产欧美精品一区二区 | 国产欧美精品一区二区三区 | 视频一区在线播放 | 欧美不卡 | 91精品国产综合久久婷婷香蕉 | 久久夜视频 | 日韩二三区 | 亚洲a网 | 亚洲日本国产 | 老司机精品福利视频 | 国产精品视频久久久 | 日韩在线观看中文字幕 | 色婷婷一区| 国产成人午夜精品影院游乐网 | 久久久www成人免费无遮挡大片 | 亚洲久久| 插插插干干干 | 亚洲第一福利网 | 欧美日韩一区二区三区四区 | 欧美精品乱码久久久久久按摩 | 国产在线精品一区二区 | 成人在线观看免费 | 97超碰人人草 | 久久久久久久一区二区三区 | 欧美精品久久久久久久久久 | 黄色片视频免费 | 久久91|