日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁(yè) > 科技  > 軟件

Go 包循環(huán)引用及對(duì)策,你學(xué)會(huì)了嗎?

來源: 責(zé)編: 時(shí)間:2024-03-18 09:37:21 171觀看
導(dǎo)讀引言從 Java 轉(zhuǎn)到 Go 的開發(fā)同學(xué),大概都會(huì)踩到第一個(gè)“坑”:Go 的包循環(huán)引用。Go 的包循環(huán)引用是什么意思呢?有一定經(jīng)驗(yàn)的開發(fā)者都知道循環(huán)依賴,比如 A 依賴了 B, B 依賴了 C ,C 又依賴了 A。這就構(gòu)成了一個(gè)循環(huán)依賴(有環(huán)圖)

引言

從 Java 轉(zhuǎn)到 Go 的開發(fā)同學(xué),大概都會(huì)踩到第一個(gè)“坑”:Go 的包循環(huán)引用。Uyl28資訊網(wǎng)——每日最新資訊28at.com

Go 的包循環(huán)引用是什么意思呢?有一定經(jīng)驗(yàn)的開發(fā)者都知道循環(huán)依賴,比如 A 依賴了 B, B 依賴了 C ,C 又依賴了 A。這就構(gòu)成了一個(gè)循環(huán)依賴(有環(huán)圖)。Uyl28資訊網(wǎng)——每日最新資訊28at.com

在 Java 里面,循環(huán)依賴是類級(jí)別的;但 Go 里要更嚴(yán)格一些:Go 的循環(huán)引用判定是 包級(jí)別的。舉個(gè)例子,包 A 下的類 A 依賴了包 B 下的類 B,類 B 又依賴了包 C 下的類 C, 類 C 又依賴了包 A 下的 D。在 Java 里面,這里并沒有構(gòu)成循環(huán)依賴。但在 Go 里面,這導(dǎo)致了包循環(huán)引用:包 A => 包 B = > 包 C => 包 A。Go 會(huì)編譯不通過:報(bào) import circle not allowed。Uyl28資訊網(wǎng)——每日最新資訊28at.com

對(duì)包依賴不太重視的人,初期會(huì)感到不適應(yīng)。本文舉幾個(gè)自己踩過的坑,作一說明。Uyl28資訊網(wǎng)——每日最新資訊28at.com

包循環(huán)引用釋例

對(duì)象導(dǎo)致的包循環(huán)引用

哎呀呀,初來乍到,一下子給我來了八個(gè)包循環(huán)引用,打擊得我有點(diǎn)不知所措了。這是怎么回事呢 ?Uyl28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片Uyl28資訊網(wǎng)——每日最新資訊28at.com

第一個(gè)循環(huán)引用,是因?yàn)樯蠄?bào)的包 agent 下對(duì)象 DetectionBase 依賴了包 denoise 下的降噪模型結(jié)果對(duì)象 HitDenoiseModel,而在某一處,HitDenoiseModel  又引用了包 agent 下的另一個(gè)對(duì)象。Uyl28資訊網(wǎng)——每日最新資訊28at.com

為什么會(huì)發(fā)生這個(gè)事情?這是因?yàn)椋瑘D省事,我直接把輸出對(duì)象放到了輸入對(duì)象的包里,不想復(fù)制一份。正確的做法是,輸入的對(duì)象只能放輸入對(duì)象,不能放輸出對(duì)象,否則依賴就會(huì)擴(kuò)大出去。Uyl28資訊網(wǎng)——每日最新資訊28at.com

如何解決?有兩種方案:Uyl28資訊網(wǎng)——每日最新資訊28at.com

  • 把 HitDenoiseModel 放在 agent 包下。然后定義另一個(gè)對(duì)象 denoise/DenoiseResultModel,將 FillHitDenoiseModel 方法移到包 denoise 下,HitDenoiseModel 賦值給 DenoiseResultModel。這樣形成了包 denoise => agent 的單向依賴,保證“輸出 =>輸入” 的單向依賴。不過,這種方法還是存在“篡改”原始數(shù)據(jù)的小罪行。
  • 不對(duì) DetectionBase 做任何變更,新創(chuàng)建一個(gè)包和對(duì)象,把 HitDenoiseModel 放在新創(chuàng)建對(duì)象里,同時(shí)將 FillHitDenoiseModel 方法移到新創(chuàng)建對(duì)象的包下。3

啟示:避免篡改輸入對(duì)象。應(yīng)用中的對(duì)象往往是很多的,不太重視包依賴,很容易造成對(duì)象的循環(huán)引用。即使你自己能夠小心確保不出問題,也會(huì)和別人添加的類造成循環(huán)引用。Uyl28資訊網(wǎng)——每日最新資訊28at.com

發(fā)送消息與接收消息循環(huán)引用

梅開二度。又來了一個(gè)包循環(huán)引用。Uyl28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片Uyl28資訊網(wǎng)——每日最新資訊28at.com

這又是怎么回事?有了第一次經(jīng)驗(yàn),第二次就不那么慌了。先提個(gè) MR ,看看引入了哪些類。尤其是循環(huán)引用的那條鏈路。我們看到 cdc/msg 這個(gè)地方作為起點(diǎn)開始循環(huán)。為什么會(huì)有循環(huán)呢?因?yàn)槲冶緛泶蛩惆?msg 相關(guān)的消息對(duì)象和消息處理都放在一起。但這種方式很容易導(dǎo)致 循環(huán)引用。為什么呢?因?yàn)?引入消息對(duì)象的時(shí)候, 就會(huì)把包下的所有類引入的所有包都引進(jìn)來,這樣就會(huì)把 /cdc/msg/XXXReceiver 引入,進(jìn)而引入 /cdc/handler/XXXhandler, 而 msg/handler/XXXhandler 又會(huì)引入 msg/XXXSender。就導(dǎo)致了包循環(huán)引用依賴。Uyl28資訊網(wǎng)——每日最新資訊28at.com

看來之前還是隨意慣了。Uyl28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片Uyl28資訊網(wǎng)——每日最新資訊28at.com

怎么解決?把 XXXReceiver 放在包 receiver 下,把 XXXSender 放在包 sender 下即可。Uyl28資訊網(wǎng)——每日最新資訊28at.com

啟示:Uyl28資訊網(wǎng)——每日最新資訊28at.com

  • 引入類的包要小,這樣就很類似 Java 的全限定性包,減少循環(huán)引用的可能性。
  • 簡(jiǎn)單的消息對(duì)象與復(fù)雜的消息處理不要放在一起,因?yàn)橐牒?jiǎn)單的就會(huì)把復(fù)雜的引入,復(fù)雜的又會(huì)遞歸引入更多的依賴。

internal 引用了 share

一鍵三連。Uyl28資訊網(wǎng)——每日最新資訊28at.com

下圖又是怎么回事?借鑒業(yè)界最佳實(shí)踐,咱們把一個(gè)工程下的代碼分為了 internal 和 share。其中 internal 的代碼不能被其它模塊訪問,只有 share 下的代碼作為橋梁,為其它模塊提供服務(wù)。Uyl28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片Uyl28資訊網(wǎng)——每日最新資訊28at.com

這個(gè)是因?yàn)?internal/detect_config/AService 引用了 share/detect_config/BService ,然后 share/detect_config/CService 又引用了 internal/detect_config/DService。internal 包怎么能夠引用 share 下的包呢 ??jī)?nèi)部模塊怎么能夠依賴外部模塊 ?世界似乎不那么美好了。Uyl28資訊網(wǎng)——每日最新資訊28at.com

與同事討論,他們認(rèn)為,helper 不應(yīng)該依賴 service ,而應(yīng)該依賴 repository, 而我一直認(rèn)為 helper 是對(duì) service 提供服務(wù)的一種高層封裝, helper 依賴 service 是很正常。helper 依賴 repository, 看上去說得也很有道理。不過 internal 模塊依賴 share 模塊,看上去總是感覺有點(diǎn)違反單向依賴的設(shè)計(jì)原則。Uyl28資訊網(wǎng)——每日最新資訊28at.com

經(jīng)過討論后,我和同事各做了修改。我的修改是讓 helper 依賴 repository, 同事的修改是,把原來 service 拆分成公共的 service 和內(nèi)部的 service,保證 share 對(duì) internal 的單向依賴。Uyl28資訊網(wǎng)——每日最新資訊28at.com

運(yùn)行時(shí)循環(huán)依賴

即使你幸運(yùn)地逃過了包循環(huán)引用的檢測(cè),但存在運(yùn)行時(shí)循環(huán)依賴,Go 會(huì)直接卡住。Uyl28資訊網(wǎng)——每日最新資訊28at.com

一個(gè)例子如下圖所示:有若干個(gè)流程組件 A, B, C,加載到一個(gè)工廠 F 下,由一個(gè) 執(zhí)行器 E 依次從 F 中取出執(zhí)行。但是呢,在流程組件C 中,又依賴了 E 來執(zhí)行任務(wù)。這樣會(huì)導(dǎo)致循環(huán)依賴。在 Java 中,Spring 會(huì)忽略組件 C, 初始化成功,但運(yùn)行時(shí)找不到 C 而導(dǎo)致流程出錯(cuò)(可以用懶加載機(jī)制解決);但是 Go 就不那么幸運(yùn)了(也許是幸運(yùn)的,因?yàn)樗屇阍琰c(diǎn)發(fā)現(xiàn)問題)。Uyl28資訊網(wǎng)——每日最新資訊28at.com

對(duì)于這種場(chǎng)景,可以用消息隊(duì)列來解耦。Uyl28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片Uyl28資訊網(wǎng)——每日最新資訊28at.com

對(duì)策匯總

遇到包循環(huán)引用,有哪些經(jīng)驗(yàn)可循呢 ?Uyl28資訊網(wǎng)——每日最新資訊28at.com

(1) 提倡小而獨(dú)立的包。不要把大量的有關(guān)聯(lián)的類都放在一個(gè)包下。這樣,很容易因?yàn)橐粋€(gè)類的引入,而引入更多依賴,導(dǎo)致依賴不可控。Uyl28資訊網(wǎng)——每日最新資訊28at.com

(2)單向依賴原則。internal 下的類不應(yīng)當(dāng)依賴 share 下的類。因?yàn)?share 下的類一定會(huì)依賴 internal。如果 internal 又依賴 share ,就破壞了“單向依賴”原則。當(dāng)工程越來越大時(shí),一定會(huì)有一個(gè)點(diǎn)會(huì)爆發(fā)。不是不報(bào),時(shí)候未到。細(xì)分包可以緩解這種問題,但不能從根本上避免單向依賴的破壞。Uyl28資訊網(wǎng)——每日最新資訊28at.com

(3) 依賴倒置原則。盡量依賴接口,而不是具體實(shí)現(xiàn)類。Uyl28資訊網(wǎng)——每日最新資訊28at.com

(4)使用消息隊(duì)列解耦依賴。Uyl28資訊網(wǎng)——每日最新資訊28at.com

(5)相對(duì)合理的依賴方向:model => (constants, 無依賴的 model) ; dto => types => constants ;util => (dto, types, constants, models);service =>  repository => model ;helper => (repository, util, cache) ; controller => (helper, service) ;  receiver => handler => (service, helper)Uyl28資訊網(wǎng)——每日最新資訊28at.com

最后問一句:Go 為什么不允許包循環(huán)引用呢 ?聽聽 Go 語(yǔ)言作者怎么說:Uyl28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片Uyl28資訊網(wǎng)——每日最新資訊28at.com

再聽聽 AI 怎么說 :Uyl28資訊網(wǎng)——每日最新資訊28at.com

圖片Uyl28資訊網(wǎng)——每日最新資訊28at.com

小結(jié)

本文討論了幾個(gè)包循環(huán)引用的例子,并給出了相應(yīng)的對(duì)策。Uyl28資訊網(wǎng)——每日最新資訊28at.com

個(gè)人覺得,這種禁止循環(huán)引用的做法還是可取的,能培養(yǎng)良好的設(shè)計(jì)習(xí)慣。軟件開發(fā),本質(zhì)是應(yīng)對(duì)結(jié)構(gòu)復(fù)雜性的技藝。而設(shè)計(jì)思維,則是應(yīng)對(duì)結(jié)構(gòu)復(fù)雜性的重要法寶。開發(fā)人員應(yīng)多多學(xué)習(xí)設(shè)計(jì)思考,保持系統(tǒng)和架構(gòu)的優(yōu)雅。Uyl28資訊網(wǎng)——每日最新資訊28at.com

參考資料

  • go循環(huán)依賴最佳解決方案[1]

Reference

[1]go循環(huán)依賴最佳解決方案:https://juejin.cn/post/7290389972406501432Uyl28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-76488-0.htmlGo 包循環(huán)引用及對(duì)策,你學(xué)會(huì)了嗎?

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: JQuery 4.0震撼發(fā)布:這是復(fù)興還是告別?

下一篇: 業(yè)務(wù)開發(fā)做到零 bug 有多難?

標(biāo)簽:
  • 熱門焦點(diǎn)
Top 主站蜘蛛池模板: 武清区| 泽普县| 平舆县| 浦江县| 巴彦淖尔市| 榆林市| 互助| 杭州市| 秦皇岛市| 沁水县| 景洪市| 舟山市| 利川市| 杭锦后旗| 城固县| 渭南市| 长兴县| 江都市| 马龙县| 时尚| 莱西市| 三台县| 文水县| 金湖县| 双牌县| 灵台县| 吴桥县| 泗洪县| 维西| 安康市| 甘泉县| 莱州市| 滦平县| 定日县| 北碚区| 颍上县| 长岭县| 专栏| 大洼县| 万山特区| 惠州市|