欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

go循環(huán)依賴的最佳解決方案

 更新時(shí)間:2023年10月18日 09:01:48   作者:人間小傻瓜  
? import cycle not allowed(循環(huán)依賴不被允許)相信作為每一個(gè)golang語(yǔ)言使用研發(fā),都遇到過這個(gè)令人頭痛的報(bào)錯(cuò),循環(huán)依賴是指兩個(gè)或多個(gè)模塊之間互相依賴,形成了一個(gè)閉環(huán)的情況,本文會(huì)結(jié)合部分案例對(duì)解決方案進(jìn)行講解,需要的朋友可以參考下

前言:

import cycle not allowed(循環(huán)依賴不被允許)相信作為每一個(gè)golang語(yǔ)言使用研發(fā),都遇到過這個(gè)令人頭痛的報(bào)錯(cuò)。循環(huán)依賴是指兩個(gè)或多個(gè)模塊之間互相依賴,形成了一個(gè)閉環(huán)的情況。這種情況下,編譯器或解釋器無(wú)法確定應(yīng)該先加載哪個(gè)模塊,從而導(dǎo)致程序無(wú)法正常運(yùn)行。本文會(huì)結(jié)合部分案例對(duì)解決方案進(jìn)行講解。

包引用循環(huán)依賴

golang 代碼包的加載過程:

問題一:循環(huán)依賴是在上面哪一個(gè)環(huán)節(jié)報(bào)錯(cuò)?

編譯環(huán)節(jié)。 當(dāng)存在循環(huán)依賴時(shí),golang編譯代碼時(shí)會(huì)首先解析代碼包的依賴關(guān)系,然后按照依賴關(guān)系的順序進(jìn)行編譯。如果存在循環(huán)依賴,即A依賴于B,而B又依賴于A,golang會(huì)檢測(cè)到這種循環(huán)依賴關(guān)系,并報(bào)告編譯錯(cuò)誤。編譯錯(cuò)誤的具體信息會(huì)包括代碼包路徑和導(dǎo)致循環(huán)依賴的具體文件及行號(hào)。

問題二:循環(huán)依賴的危害有哪些?

對(duì)于golang來(lái)說,最大的危害就是連編譯都過不了...

問題三:go高版本是否支持從編譯環(huán)節(jié)解決循環(huán)依賴的問題?

不支持。 java解決循環(huán)依賴的方法有很多,延遲初始化或懶加載、三級(jí)緩存等都是解決包循環(huán)依賴的利器。然而golang并沒有配置或注解來(lái)解決循環(huán)依賴的問題。

相比于代碼的執(zhí)行效率,Go更加注重編譯的速度。雖然Go的編譯器不會(huì)像C/C++那樣花費(fèi)大量的時(shí)間生成高效的機(jī)器碼,但它們更專注于快速的編譯大量的源代碼。支持循環(huán)依賴會(huì)導(dǎo)致代碼編譯時(shí)間增加,因?yàn)槊看胃淖兡硞€(gè)依賴項(xiàng)都會(huì)重新編譯整個(gè)依賴樹。此外,循環(huán)依賴還增加了鏈接時(shí)間和使獨(dú)立測(cè)試和包重用的難度(由于包之間可能不可靠分離,單元測(cè)試也會(huì)變得更加困難)。

解決方案:

重新梳理領(lǐng)域模型

在遇到循環(huán)依賴的時(shí)候,最先考慮的就是模塊分層是否不清晰,領(lǐng)域劃分是否準(zhǔn)確。下圖是最基礎(chǔ)的DDD模型。

下層不依賴上層

我們應(yīng)該有著清晰的認(rèn)知,在服務(wù)中,哪個(gè)模塊是下層,哪個(gè)是上層。

如數(shù)據(jù)庫(kù)dao層,reids包這些都是處于基礎(chǔ)設(shè)施層的模塊,那么其就不能依賴于領(lǐng)域?qū)舆壿嫿涌?。如果想要?shí)現(xiàn)寫入數(shù)據(jù)庫(kù)并寫入redis,這個(gè)邏輯就影響在領(lǐng)域?qū)訉?shí)現(xiàn)而不是在基礎(chǔ)設(shè)施層。

同層不能互相調(diào)用

舉個(gè)例子,假設(shè)我們有外呼模塊和短信模塊,部分場(chǎng)景在外呼后要自動(dòng)發(fā)送短信,部分場(chǎng)景發(fā)完短信后要機(jī)器人外呼,就出現(xiàn)循環(huán)依賴了。我們可以有兩種解決方案,1.將互相調(diào)用的邏輯往上層移動(dòng)。2.將兩個(gè)模塊放在一起作為一個(gè)統(tǒng)一的用戶觸達(dá)模塊。

有些時(shí)候,在沒出現(xiàn)循環(huán)依賴的時(shí)候,我們可能并沒有意識(shí)到出現(xiàn)了同層調(diào)用的情況,等到出現(xiàn)循環(huán)依賴再想保持良好的架構(gòu)模式就需要代碼重構(gòu)了。 約束是死的,人是活的。總是有一些場(chǎng)景,你不得不在同層模塊間進(jìn)行調(diào)用,但是改造的消耗的成本遠(yuǎn)比不遵守準(zhǔn)則來(lái)得低,則進(jìn)行同層間調(diào)用也不是什么丟臉的事。

目前很多服務(wù)還是依賴于傳統(tǒng)的MVC模型進(jìn)行開發(fā),三層結(jié)構(gòu)使得所有的業(yè)務(wù)邏輯都耦合在service(業(yè)務(wù)邏輯)層,雖然可閱讀性下降了,但是也降低了循環(huán)依賴問題發(fā)生(所有的業(yè)務(wù)邏輯都在一個(gè)包下)。DDD在給我們帶來(lái)高可維護(hù)性,可閱讀性的同時(shí),也需要我們更清晰的對(duì)業(yè)務(wù)有明確的認(rèn)知和一定的技術(shù)支持。兩者不論好壞,各有各自適用的業(yè)務(wù)場(chǎng)景。

依賴倒置原則

依賴倒置又叫做依賴反轉(zhuǎn)。依賴關(guān)系如下圖所示:

依賴倒置是解決循環(huán)依賴很常用的技巧,但是不是所有的循環(huán)依賴場(chǎng)景都適用依賴倒置來(lái)解決,我們通常會(huì)在架構(gòu)設(shè)計(jì)或者通用能力接口的實(shí)現(xiàn)上使用到它,恰當(dāng)?shù)氖褂茫梢越档痛a耦合性,提高代碼可讀性和可維護(hù)性。

舉例一個(gè)生活中的例子:

我們運(yùn)營(yíng)平臺(tái)最常見的場(chǎng)景就是審核,在增信提額場(chǎng)景中,會(huì)先對(duì)用戶提交的資料進(jìn)行審核,再對(duì)用戶提交的申請(qǐng)進(jìn)行審核。目前,人審已經(jīng)不滿足我們?cè)V求,我們需要提供一個(gè)自動(dòng)審核的能力,在審核員完成對(duì)資料的審核后,自動(dòng)觸發(fā)自動(dòng)審核完成對(duì)申請(qǐng)維度的審核。如下圖:

上圖左邊,如果我們單獨(dú)的抽出一個(gè)文件夾作為自動(dòng)審核模塊,資料審核完成需要發(fā)起自動(dòng)審核,自動(dòng)審核需要執(zhí)行申請(qǐng)審核,所以上面自動(dòng)審核模塊和增信提額模塊就形成了循環(huán)依賴的關(guān)系。

當(dāng)我們進(jìn)行依賴反轉(zhuǎn)后,就可以得到右圖。將自動(dòng)審核模塊分成兩個(gè)文件夾,一個(gè)是抽象接口,一個(gè)是邏輯實(shí)現(xiàn)。抽象接口不依賴于邏輯實(shí)現(xiàn),所以自動(dòng)審核入口不再依賴于增信提額模塊中的申請(qǐng)審核。自動(dòng)審核入口成為最底層模塊,所有的模塊都可以隨意調(diào)用,一定不會(huì)產(chǎn)生循環(huán)依賴。對(duì)于資料審核完成執(zhí)行申請(qǐng)審核場(chǎng)景下,資料審核是高層,自動(dòng)審核實(shí)現(xiàn)邏輯是低層,他們都依賴于抽象。

這是一個(gè)很典型的通過依賴反轉(zhuǎn)來(lái)實(shí)現(xiàn)提供一個(gè)通用能力的例子。除了基礎(chǔ)設(shè)施層以外,我們所有實(shí)現(xiàn)的通用能力接口如果包含了業(yè)務(wù)邏輯,都應(yīng)將其通過依賴反轉(zhuǎn)來(lái)與實(shí)現(xiàn)解耦??梢詮氐捉鉀Q通用能力包導(dǎo)致的循環(huán)依賴問題。

分層架構(gòu)中也經(jīng)常會(huì)使用依賴反轉(zhuǎn)來(lái)改變不同層之間的依賴關(guān)系以此達(dá)到改進(jìn)的目的。如下面一種場(chǎng)景:

將基礎(chǔ)設(shè)施層放到所有層最上方。其優(yōu)點(diǎn)有:

  • 基礎(chǔ)設(shè)施層可以調(diào)用其他層所有的方法。

  • 基礎(chǔ)設(shè)施層可以直接使用領(lǐng)域?qū)佣x的實(shí)體等其他層的結(jié)構(gòu)化信息。

事件驅(qū)動(dòng)架構(gòu)

事件驅(qū)動(dòng)架構(gòu)是一種松耦合、分布式的架構(gòu)??梢酝ㄟ^mq來(lái)實(shí)現(xiàn)。

事件驅(qū)動(dòng)架構(gòu)體系結(jié)構(gòu)具備以下三個(gè)能力:

  • 事件收集:負(fù)責(zé)收集各種應(yīng)用產(chǎn)生的數(shù)據(jù)變化,例如訂單創(chuàng)建、退換貨等狀態(tài)變更。這些變化可以被用于監(jiān)控業(yè)務(wù)流程、識(shí)別異常情況和觸發(fā)警報(bào)等。

  • 事件處理:對(duì)采集到的數(shù)據(jù)變化進(jìn)行脫敏處理,并進(jìn)行初步的過濾和篩選,以確保數(shù)據(jù)的準(zhǔn)確性和可靠性。這有助于減少誤報(bào)和漏報(bào)的風(fēng)險(xiǎn),并為上層應(yīng)用提供有價(jià)值的數(shù)據(jù)。

  • 事件路由:根據(jù)數(shù)據(jù)變化的來(lái)源和性質(zhì),將事件路由分發(fā)至下游產(chǎn)品,以實(shí)現(xiàn)更高效的業(yè)務(wù)處理和分析。這可以幫助企業(yè)更好地了解自己的業(yè)務(wù)狀況,并根據(jù)需要進(jìn)行優(yōu)化和改進(jìn)。

舉例:

同樣是上面增信提額的例子,如果這個(gè)時(shí)候,放心借產(chǎn)品審核也需要進(jìn)行自動(dòng)審核了,那我們是否可以按如下架構(gòu)進(jìn)行調(diào)整。

我們將自動(dòng)審核抽成一個(gè)獨(dú)立服務(wù),通過mq解耦自動(dòng)審核回調(diào)業(yè)務(wù)系統(tǒng)的邏輯。至此即解決了循環(huán)依賴的問題,又對(duì)自動(dòng)審核服務(wù)與業(yè)務(wù)系統(tǒng)進(jìn)行了明確的劃分。缺陷是:對(duì)于原流程改造成本大。

無(wú)論是依賴倒置還是事件驅(qū)動(dòng)架構(gòu),都能解決以上循環(huán)依賴的問題,**沒有最好的方案,只有最適用的方案。**依賴倒置適用于同步場(chǎng)景。而事件驅(qū)動(dòng)架構(gòu)適用于異步的場(chǎng)景。

丑陋的解決方式(不推薦 不推薦 不推薦)

通過go:linkname注釋來(lái)避免導(dǎo)入包。

go:linkname是一個(gè)編譯器指令(格式://go:linkname localname [importpath.name] ) 。這個(gè)特殊指令的作用域不是緊跟的下一行代碼,而是在同一個(gè)包下生效。

//go:linkname 告訴Go的編譯器本本地的變量或方法 localname 鏈接到指令的變量或方法 importpath.name 上go:linkname定義 。

這是go官方黑科技,官方也不建議使用。

結(jié)論:

  • 遇到循環(huán)依賴不要慌。

  • 先梳理出上下層模塊,切記,上層不依賴于下層

  • 如果為同層模塊,則考慮同層合并或者邏輯上移。

  • 同步場(chǎng)景的通用接口考慮用依賴倒置原則,上層下層均依賴于抽象。

  • 異步場(chǎng)景考慮用事件驅(qū)動(dòng)模式。

  • 永遠(yuǎn)不要考慮linkname解決。

以上就是go循環(huán)依賴的最佳解決方案的詳細(xì)內(nèi)容,更多關(guān)于go循環(huán)依賴解決的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Golang切片刪除指定元素的三種方法對(duì)比

    Golang切片刪除指定元素的三種方法對(duì)比

    Go語(yǔ)言并沒有提供用于刪除元素的語(yǔ)法或接口,而是通過利用切片本身的特性來(lái)刪除元素—追加元素,這篇文章主要給大家介紹了關(guān)于Golang切片刪除指定元素的三種方法,需要的朋友可以參考下
    2022-06-06
  • 詳解Golang中g(shù)cache模塊的基本使用

    詳解Golang中g(shù)cache模塊的基本使用

    這篇文章主要通過結(jié)合商業(yè)項(xiàng)目的使用場(chǎng)景,為大家介紹了gcache的基本使用、緩存控制以及淘汰策略。使用gcache做緩存處理,簡(jiǎn)單方便易上手
    2022-11-11
  • Golang依賴注入工具digo的使用詳解

    Golang依賴注入工具digo的使用詳解

    這篇文章主要為大家詳細(xì)介紹了Golang中依賴注入工具digo的使用,文中的示例代碼講解詳細(xì),具有一定的學(xué)習(xí)價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-06-06
  • 在Go中創(chuàng)建自定義錯(cuò)誤的方式總結(jié)

    在Go中創(chuàng)建自定義錯(cuò)誤的方式總結(jié)

    在程序開發(fā)中錯(cuò)誤處理是至關(guān)重要的,下面這篇文章主要給大家介紹了關(guān)于在Go中創(chuàng)建自定義錯(cuò)誤的方式,文中通過代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Go具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2024-01-01
  • 詳解Go語(yǔ)言中new和make關(guān)鍵字的區(qū)別

    詳解Go語(yǔ)言中new和make關(guān)鍵字的區(qū)別

    本篇文章來(lái)介紹一道非常常見的面試題,到底有多常見呢?可能很多面試的開場(chǎng)白就是由此開始的。那就是 new 和 make 這兩個(gè)內(nèi)置函數(shù)的區(qū)別,希望對(duì)大家有所幫助
    2023-03-03
  • go-python 庫(kù)使用應(yīng)用案例

    go-python 庫(kù)使用應(yīng)用案例

    本文深入探討了如何使用Go-Python庫(kù)進(jìn)行跨語(yǔ)言編程,以及在實(shí)際應(yīng)用中的各種技巧和應(yīng)用案例,在結(jié)語(yǔ)中,我們將對(duì)Go-Python庫(kù)的使用方法與技巧進(jìn)行總結(jié),并展望Go與Python混合編程的未來(lái)發(fā)展
    2024-03-03
  • Go中的關(guān)鍵字any interface是否會(huì)成為歷史

    Go中的關(guān)鍵字any interface是否會(huì)成為歷史

    這篇文章主要為大家介紹了Go中的關(guān)鍵字any interface是否會(huì)成為歷史的講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Golang實(shí)現(xiàn)四層負(fù)載均衡的示例代碼

    Golang實(shí)現(xiàn)四層負(fù)載均衡的示例代碼

    做開發(fā)的同學(xué)應(yīng)該經(jīng)常聽到過負(fù)載均衡的概念,今天我們就來(lái)實(shí)現(xiàn)一個(gè)乞丐版的四層負(fù)載均衡,并用它對(duì)mysql進(jìn)行負(fù)載均衡測(cè)試,感興趣的可以了解一下
    2023-07-07
  • Go語(yǔ)言對(duì)JSON數(shù)據(jù)進(jìn)行序列化和反序列化

    Go語(yǔ)言對(duì)JSON數(shù)據(jù)進(jìn)行序列化和反序列化

    這篇文章介紹了Go語(yǔ)言對(duì)JSON數(shù)據(jù)進(jìn)行序列化和反序列化的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07
  • Go語(yǔ)言defer的一些神奇規(guī)則示例詳解

    Go語(yǔ)言defer的一些神奇規(guī)則示例詳解

    這篇文章主要為大家介紹了Go語(yǔ)言defer的一些神奇規(guī)則示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11

最新評(píng)論