1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Go整潔架構(gòu)模版,建議收藏

        共 10417字,需瀏覽 21分鐘

         ·

        2021-09-02 20:31

        本文翻譯自 https://github.com/evrone/go-clean-template,由于本人翻譯水平有限,翻譯不當(dāng)之處煩請(qǐng)指出。希望大家看了這篇文章能有所幫助。感謝捧場(chǎng)。
        概括

        模板的作用 :

        • 如何組織項(xiàng)目并防止它變成一坨意大利面條式的代碼。
        • 在哪里存放業(yè)務(wù)邏輯,使其保持獨(dú)立,整潔和可擴(kuò)展。
        • 如何在微服務(wù)擴(kuò)展時(shí)不失控

        模版使用了 Robert Martin ( 也叫 Bob 叔叔 ) 的原則[1]。

        Go-clean-template[2] 此倉庫由 Evrone[3] 創(chuàng)建及維護(hù)。

        目錄內(nèi)容

        • 快速開始
        • 項(xiàng)目結(jié)構(gòu)
        • 依賴注入
        • 整潔架構(gòu)之道

        快速開始

        本地開發(fā)

        # Postgres, RabbitMQ
        $ make compose-up
        # Run app with migrations
        $ make run

        集成測(cè)試 ( 可以在 CI 中運(yùn)行 )

        # DB, app + migrations, integration tests
        $ make compose-up-integration-test

        項(xiàng)目結(jié)構(gòu)

        ├── cmd
        │   └── app
        │       └── main.go
        ├── config
        │   ├── config.go
        │   └── config.yml
        ├── docs
        │   ├── docs.go
        │   ├── swagger.json
        │   └── swagger.yaml
        ├── go.mod
        ├── go.sum
        ├── integration-test
        │   ├── Dockerfile
        │   └── integration_test.go
        ├── internal
        │   ├── app
        │   │   ├── app.go
        │   │   └── migrate.go
        │   ├── delivery
        │   │   ├── amqp_rpc
        │   │   │   ├── router.go
        │   │   │   └── translation.go
        │   │   └── http
        │   │       └── v1
        │   │           ├── error.go
        │   │           ├── router.go
        │   │           └── translation.go
        │   ├── domain
        │   │   └── translation.go
        │   └── service
        │       ├── interfaces.go
        │       ├── repo
        │       │   └── translation_postgres.go
        │       ├── translation.go
        │       └── webapi
        │           └── translation_google.go
        ├── migrations
        │   ├── 20210221023242_migrate_name.down.sql
        │   └── 20210221023242_migrate_name.up.sql
        └── pkg
            ├── httpserver
            │   ├── options.go
            │   └── server.go
            ├── logger
            │   ├── interface.go
            │   ├── logger.go
            │   └── zap.go
            ├── postgres
            │   ├── options.go
            │   └── postgres.go
            └── rabbitmq
                └── rmq_rpc
                    ├── client
                    │   ├── client.go
                    │   └── options.go
                    ├── connection.go
                    ├── errors.go
                    └── server
                        ├── options.go
                        └── server.go

        cmd/app/main.go

        配置和日志實(shí)例的初始化,main 函數(shù)中調(diào)用internal/app/app.go 文件中 的 Run 函數(shù),main 函數(shù)將會(huì)在此 "延續(xù)"。

        config

        配置。首先讀取 config.yml,然后用環(huán)境變量覆蓋相匹配的 yaml 配置。配置的結(jié)構(gòu)體在 config.go 文件中。env-required: true 結(jié)構(gòu)體標(biāo)簽強(qiáng)制您指定一個(gè)值 ( 在 yaml 或在環(huán)境變量中 )。

        對(duì)于配置讀取,我們選擇 cleanenv[4] 庫。它在 GitHub 上沒有很多 star,但很簡單且滿足所有的需求。

        從 yaml 中讀取配置違背了12 要素,但在實(shí)踐中,它比從環(huán)境變量中讀取整個(gè)配置更方便。假設(shè)默認(rèn)值定義在 yaml 中,敏感的變量定義在環(huán)境變量中。

        docs

        Swagger 文檔。可以由 swag[5] 庫自動(dòng)生成。而你不需要自己改正任何事情。

        integration-test

        集成測(cè)試。它們作為單獨(dú)的容器啟動(dòng),緊挨著應(yīng)用程序容器。使用 go-hit[6] 測(cè)試 REST API 非常方便。

        internal/app

        在 app.go 文件中一般會(huì)有一個(gè) Run 函數(shù),它“延續(xù)”了main函數(shù)。

        這是創(chuàng)建所有主要對(duì)象的地方。依賴注入通過“ New...”構(gòu)造函數(shù) ( 參見依賴注入 ) 。這種技術(shù)允許我們使用依賴注入原則對(duì)應(yīng)用程序進(jìn)行分層,使得業(yè)務(wù)邏輯獨(dú)立于其他層。

        接下來,為了優(yōu)雅的完成,我們啟動(dòng)服務(wù)并在select中等待特定的信號(hào)。如果 app.go 代碼越來越多,可以將其拆分為多個(gè)文件。

        對(duì)于大量的注入,可以使用 wire[7] 庫 ( wire 是一個(gè)代碼生成工具,它使用依賴注入自動(dòng)連接組件)。

        migrate.go 文件用于數(shù)據(jù)庫自動(dòng)遷移。如果指定了 migrate 標(biāo)簽的參數(shù),則會(huì)包含它。例如 :

        $ go run -tags migrate ./cmd/app

        internal/delivery

        服務(wù)的handler層 ( MVC 控制器 )。模板展示了兩個(gè)服務(wù):

        • RPC ( RabbitMQ 用于傳遞消息 )
        • REST HTTP ( GIN 框架 )

        服務(wù)的路由也以同樣的風(fēng)格編寫 :

        • Handlers按照應(yīng)用領(lǐng)域分組 ( 按公共基礎(chǔ) )
        • 對(duì)于每個(gè)組,都創(chuàng)建自己的路由結(jié)構(gòu),以及處理接口路徑的方法
        • 業(yè)務(wù)邏輯的結(jié)構(gòu)被注入到路由結(jié)構(gòu)中,由handlers處理調(diào)用

        internal/delivery/http

        簡單的 REST 版本控制。對(duì)于 v2,我們需要添加具有相同內(nèi)容的 http/v2 文件夾。在 internal/app 程序文件中添加以下行 :

        handler := gin.New()
        v1.NewRouter(handler, translationService)
        v2.NewRouter(handler, translationService)

        你可以使用任何其他的 HTTP 框架甚至是標(biāo)準(zhǔn)的 net/http 庫來代替 Gin。

        在 v1/router.go 和上面的 handler 方法中,有一些注釋是用 swag庫來生成 swagger 文檔的。

        internal/domain

        業(yè)務(wù)邏輯的實(shí)體 ( 模型 ) 可以在任何層中使用。也可以有方法,例如,用于驗(yàn)證。

        internal/service

        業(yè)務(wù)邏輯

        • 方法按應(yīng)用領(lǐng)域分組 ( 在公共的基礎(chǔ)上 )
        • 每個(gè)組都有自己的結(jié)構(gòu)
        • 一個(gè)文件一個(gè)結(jié)構(gòu)

        Repositories、 webapi、 rpc 和其他業(yè)務(wù)邏輯結(jié)構(gòu)被注入到業(yè)務(wù)邏輯結(jié)構(gòu)中 ( 見依賴注入 )。

        internal/service/repo

        repository 是業(yè)務(wù)邏輯使用的抽象存儲(chǔ) ( 數(shù)據(jù)庫 )。

        internal/service/webapi

        它是業(yè)務(wù)邏輯使用的抽象 web API。例如,它可能是業(yè)務(wù)邏輯通過 REST API 訪問的另一個(gè)微服務(wù)。包的名稱根據(jù)用途而變化。

        pkg/rabbitmq

        RabbitMQ RPC 模式 :

        • RabbitMQ 內(nèi)部沒有路由
        • 使用Exchange fanout 廣播模式,將1 個(gè)獨(dú)立隊(duì)列綁定到其中,這是最高效的配置。
        • 重新連接斷開丟失的連接

        依賴注入

        為了消除業(yè)務(wù)邏輯對(duì)外部包的依賴,使用了依賴注入。

        例如,通過 NewService 構(gòu)造函數(shù),我們將依賴注入到業(yè)務(wù)邏輯的結(jié)構(gòu)中。這使得業(yè)務(wù)邏輯獨(dú)立 ( 便于移植 )。我們可以重寫接口的實(shí)現(xiàn),而不需要對(duì) service 包進(jìn)行更改。

        package service

        import (
            // Nothing!
        )

        type Repository interface {
            Get()
        }

        type Service struct {
            repo Repository
        }

        func NewService(r Repository) *Service{
            return &Service{r}
        }

        func (s *Service) Do()  {
            s.repo.Get()
        }

        它還允許我們自動(dòng)生成模擬參數(shù) ( 例如使用 mockery[8] ) 和輕松地編寫單元測(cè)試。

        我們可以不受特定實(shí)現(xiàn)的約束,來將一個(gè)組件更改為另一個(gè)組件。如果新組件實(shí)現(xiàn)了該接口,則業(yè)務(wù)邏輯中不需要進(jìn)行任何更改。

        整潔架構(gòu)之道

        關(guān)鍵點(diǎn)

        程序員在編寫了大量代碼后才意識(shí)到應(yīng)用程序的最佳架構(gòu)。

        一個(gè)好的架構(gòu)允許盡可能推遲決策。

        主要原則

        Dependency Inversion ( 與 SOLID 相同 ) 是依賴倒置的原則。依賴關(guān)系的方向是從外層到內(nèi)層。由于這個(gè)原因,業(yè)務(wù)邏輯和實(shí)體仍然獨(dú)立于系統(tǒng)的其他部分。

        因此,應(yīng)用程序分為內(nèi)部和外部兩個(gè)層次 :

        • 業(yè)務(wù)邏輯 ( 使用 Go 標(biāo)準(zhǔn)庫 )
        • 工具 ( 數(shù)據(jù)庫、其他服務(wù)、消息代理、任何其他包和框架 )
        Clean Architecture

        業(yè)務(wù)邏輯的內(nèi)層應(yīng)該是整潔的,它應(yīng)該 :

        • 沒有從外層導(dǎo)入的包
        • 只使用標(biāo)準(zhǔn)庫的功能
        • 通過接口調(diào)用外層 !

        業(yè)務(wù)邏輯對(duì) Postgres 或詳細(xì)的 web API 一無所知。業(yè)務(wù)邏輯應(yīng)該具有一個(gè)用于處理抽象數(shù)據(jù)庫或抽象 web API 的接口。

        外層還有其他限制 :

        • 這一層的所有組成部分都不知道彼此的存在。如何從一個(gè)工具調(diào)用另一個(gè)工具?不是直接,而是只能通過內(nèi)層的業(yè)務(wù)邏輯來調(diào)用。
        • 對(duì)內(nèi)層的所有調(diào)用都是通過接口來完成的
        • 數(shù)據(jù)以便于業(yè)務(wù)邏輯的格式傳輸 ( internal/domain )

        例如,你需要從 HTTP ( 控制器 ) 訪問數(shù)據(jù)庫。HTTP 和數(shù)據(jù)庫都在外層,這意味著它們對(duì)彼此一無所知。它們之間的通信是通過 service ( 業(yè)務(wù)邏輯 ) 進(jìn)行的 :

            HTTP > service
                   service > repository (Postgres)
                   service < repository (Postgres)
            HTTP < service

        符號(hào) > 和 < 通過接口顯示層與層邊界的交集,如圖所示 :

        Example

        或者更復(fù)雜的業(yè)務(wù)邏輯 :

            HTTP > service
                   service > repository
                   service < repository
                   service > webapi
                   service < webapi
                   service > RPC
                   service < RPC
                   service > repository
                   service < repository
            HTTP < service

        層級(jí)

        Example

        整潔架構(gòu)的術(shù)語

        • 實(shí)體是業(yè)務(wù)邏輯操作的結(jié)構(gòu)。它們位于 internal/domain 文件夾中。Domain 暗示我們堅(jiān)持 DDD ( 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì) ) 的原則,這在一定程度上是正確的。在 MVC 術(shù)語中,實(shí)體就是模型。
        • 用例是位于 internal/service 中的業(yè)務(wù)邏輯。從整潔架構(gòu)的角度來看,調(diào)用業(yè)務(wù)邏輯使用 service 一詞不是習(xí)慣的用法,但是對(duì)于一個(gè)包名稱來說,使用一個(gè)單詞 ( service ) 比使用兩個(gè)單詞 ( use case ) 更方便。

        業(yè)務(wù)邏輯直接交互的層通常稱為基礎(chǔ)設(shè)施層。它們可以是存儲(chǔ)庫 internal/service/repo、web API internal/service/webapi、任何pkg,以及其他微服務(wù)。在模板中,_ infrastructure 包位于 internal/service 中。

        你可以根據(jù)需要去選擇如何調(diào)用入口點(diǎn)。選項(xiàng)如下 :

        • delivery (in our case)
        • controllers
        • transport
        • gateways
        • entrypoints
        • primary
        • input

        附加層

        經(jīng)典版本的 整潔架構(gòu)之道[9] 是為構(gòu)建大型單體應(yīng)用程序而設(shè)計(jì)的,它有4層。

        在最初的版本中,外層被分為兩個(gè)以上的層,兩層之間也存在相互依賴關(guān)系倒置 ( 定向內(nèi)部 ),并通過接口進(jìn)行通信。

        在邏輯復(fù)雜的情況下,內(nèi)層也分為兩個(gè)( 接口分離 )。

        復(fù)雜的工具可以被劃分成更多的附加層,但你應(yīng)該在確實(shí)需要時(shí)再添加層。

        替代方法

        除了整潔架構(gòu)之道,洋蔥架構(gòu)和六邊形架構(gòu) ( 端口適配器模式 ) 是類似的。兩者都是基于依賴倒置的原則。端口和適配器模式非常接近于整潔架構(gòu)之道,差異主要在術(shù)語上。

        類似的項(xiàng)目

        • https://github.com/bxcodec/go-clean-arch
        • https://github.com/zhashkevych/courses-backend

        擴(kuò)展閱讀鏈接

        • 整潔架構(gòu)之道[10]
        • 12 要素[11]

        參考資料

        [1] 

        原則: https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

        [2] 

        Go-clean-template: https://evrone.com/go-clean-template?utm_source=github&utm_campaign=go-clean-template

        [3] 

        Evrone: https://evrone.com/?utm_source=github&utm_campaign=go-clean-template

        [4] 

        cleanenv: https://github.com/ilyakaznacheev/cleanenv

        [5] 

        swag: https://github.com/swaggo/swag

        [6] 

        go-hit: https://github.com/Eun/go-hit

        [7] 

        wire: https://github.com/google/wire

        [8] 

        mockery: https://github.com/vektra/mockery

        [9] 

        整潔架構(gòu)之道: https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

        [10] 

        整潔架構(gòu)之道: https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

        [11] 

        12 要素: https://12factor.net/ru/





        推薦閱讀


        福利

        我為大家整理了一份從入門到進(jìn)階的Go學(xué)習(xí)資料禮包,包含學(xué)習(xí)建議:入門看什么,進(jìn)階看什么。關(guān)注公眾號(hào) 「polarisxu」,回復(fù) ebook 獲??;還可以回復(fù)「進(jìn)群」,和數(shù)萬 Gopher 交流學(xué)習(xí)。

        瀏覽 83
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            日本韩国高清无码| 狼友视频一国产| 日韩高清无码一区| 免费无码一区二区三区| 成人毛片| 亚洲中文字幕一| 亚洲第一色图| 毛片成人网| 蜜桃系列一区二区精品| 天堂网色| 九月丁香婷婷| 国产高清无码免费在线观看| 久久高清亚洲| 日韩在线高清视频| 白丝久久| 国产女人免费| а√天堂中文最新版8| 日本久久久久久久久视频在线观看| 国产成人久久777777黄蓉| 色中文字幕| av在线精品| 五月天激情电影| 欧美黄片免费观看| av中文字幕网| 人妻精品一区二区| 国产精品一区二区性色AV| 日韩特级毛片| AV色片| 日本一区免费| 日韩精品一区二区三区中文在线 | 午夜久久电影| 精品蜜桃秘一区二区三区在线播放| 欧美一级A片在线观看| 午夜黄色视频在线观看| 久草在| 99黄网| 91欧美性爱| 精品无码视频在线| 婷婷五月中文| 成人做爰黄A片免费| 亚洲成人在线观看视频| 久草国产在线视频| 国产精品无码激情| 2024AV在线| 黄片国产| 777三级| 一级a免一级a做片免费| 亚洲无码AV一区二区| 91看片看婬黄大片女跟女| 国产中文字幕波多| 欧美日韩在线视频免费观看| 欧美人操逼视频| 在线观看国产小视频| 人人看人人摸人人草| 黑人一区二区| 欧美午夜伦理| 欧美人妻日韩精品| 丁香五月网站| 黄色国产免费| 五月在线视频| 天堂国产| 色婷婷色99国产综合精品| 日韩免费无码视频| 国产在线拍揄自揄拍无码福利 | 欧美亚洲日本| 中国九九盗摄偷拍偷看| 五十路av| 一个色综合网| 操逼视频在线免费观看| 最近中文字幕免费mv第一季歌词強上| 国产乱子伦-区二区三区| 99热这里都是精品| 91在线免费视频| 日韩一级一片内射视频4K| 久久人精品| 日韩成人黄色视频| 青青操人人操| 996热re视频精品视频这里 | 超碰欧美| 91超碰在线| 色四播播| 欧美视频综合网| 久色婷婷在线| 少妇搡BBBB搡BBB搡造水多,| 天天操天天干天天| 夜夜骑天天| 日本色网址| 日韩精品免费在线观看| 五月婷婷丁香在线| 色色视频在线观看| 国产天堂网| 波多野结衣在线无码| 成人精品在线视频| 波多野结衣性爱视频| 在线你懂的| 青草大香蕉| 影音先锋女人资源| 国精品无码一区二区三区在线秋菊| 亚洲成人高清在线| 18啪啪网站| 亚洲无码图| 粉嫩小泬BBBB免费看-百度 | 久热中文字幕| 黄工厂精品视频在线播| 欧美96| av天堂电影网| 91精品人妻一区二区三区四区 | 国产在线性爱视频| 三级黄色免费网站| 18禁av在线| 欧美一级特黄A片免费| 99视频在线观看免费| 中文字字幕在线中文乱码| 91精品又粗又猛又爽| 99re6热在线精品视频功能| 伊人私人影院| 亚洲一区二区视频在线观看| 人人操人人模| 操逼网首页123| 九色国产在线| 亚洲高清无码一区| 99久久99| 亚洲综合免费观看高清完整版在线 | 欧美怡春院| 蜜桃网一区二区| 1024大香蕉| 超碰牛牛| 亚久久| 做爱无码| 久久系列| 一纹A片免费观看| 黑人av在线观看| 曰韩一级片| 国产精品扒开腿做爽爽爽视频| 欧美老女人性爱视频| 日韩精品久久久久久久酒店| 国产va在线观看| 亚洲欧美中文字幕| а√天堂中文最新版8| 激情麻豆| 国产avwww| 九九久久99| 青青草激情视频| 波多野结衣黄色视频| 成人性爱福利视频| 七区九区一区在线| 99在线精品视频观看| 处破女初破全过免费看| 天天色天天日天天干| 爱爱视频免费| 68久久久| 国产精品亚洲一区| 国产无码影视| 四虎成人精品在永久免费| 日韩精品成人无码免费| 国产黄色在线视频| 大鸡巴日| 伊人网导航| a无码视频在线观看| 91资源超碰| www.插插插| 伊人狼人香蕉| 国产精品99久久免费黑人人妻 | 国产亚洲无码激情前后夹击| 一区二区三区四区五区无码| 男女啪啪网| 色婷婷成人做爰A片免费看网站| 男女精品一区| 国产精品在线免费| 噜噜噜在线视频| 69精品无码成人久久久久久| 夜夜操夜夜爽| 午夜精品久久久久久久久久久久| 青草视屏| 日B视频在线观看| 亚洲第一免费视频| 蜜桃av秘无码一区三区四| 亚洲国产成人va| 在线播放高清无码| 日韩成人网站在线观看| 国产女人视频| 黄色成人网站在线观看| 白嫩无码| 99国产精品久久久久久久成人| 黑巨茎大战欧美白妞小说| 成人毛片在线观看| 2025毛片| 日韩中文字幕视频在线| 探花在线综合| 九九热免费视频| 搡BBB搡BBBB搡BBBB-百度| 精品人妻一区二区三区日产乱码| 亚洲中文字幕在线视频播放| 无码窝在线观看| 亚洲视频第一页| 国产青娱乐在线视频| 亚洲黄色在线观看视频| 东方a在线| 免费看黄色大片| 免费aa片| 日韩专区中文字幕| 午夜黄色小视频| 九九热精品在线| 国产女主播在线播放| 国产91久久婷婷一区二区| 国产日产亚洲精品| 天天撸视频| 波多野结衣网| www国产在线| 中文字幕av一区二区| 亚洲高清无码视频在线观看| 加勒比日韩无码| 东京热久久综合| 国产婷婷色一区二区三区| 黄色激情五月天| 无码国精品一区二区免费蜜桃| 噜噜噜在线视频| 国产免费一区二区| 欧美三级长视频| 俺去也俺去啦| 国产精品77777| 国产美女高潮| 51一区二区三区| 久久午夜无码鲁丝| 豆花视频logo进入官网| 免费黄色小视频| 亚洲国产中文字幕在线播放| 五月天高清无码| 91亚洲电影| 学生妹作爱片| 久热9| 国产又爽又黄A片| 91麻豆福利在线| TheAV精尽人亡av| 四虎成人精品无码永久在线的客服| 中文字幕不卡+婷婷五月| 无码999| 欧美日韩中文字幕在线视频| 欧美成人自拍| 午夜亚洲福利视频| 天堂网婷婷| 精品综合网| 欧美色图视频网站| 国产AV直播| 亚洲欧洲日韩| 天天射综合| 福利视频在线| 中文字幕无码视频在线观看| 日韩a| 内射视频网| 艹逼国产| 99精品视频在线| 欧美在线视频你懂的| 2022黄片| 91在线亚洲| 最近中文字幕av| 91九色首页| 久久久一区二区| 欧美最猛黑A片黑人猛交蜜桃视频| 热久久这里只有精品| 综合网亚洲| 看免费黄色录像| 日本熟妇高潮BBwBBwBBw| 高潮视频在线观看| 国产在线视频第一页| 欧美成人超碰| 日韩欧美一级片| 精品国产精品三级精品AV网址| 亚洲欧洲av| 亚洲精品综合| 99精品视频在线免费观看| 欧美亚洲中文| 五月天青青草超碰免费公开在线观看| 天堂8在线视频| 做爱无码| 三级片在线观看网站| 国产一级片电影| 水蜜桃一曲二区| 在线观看成人三级片| 波多野结衣亚洲视频| 成人一级A片| 欧美日韩a片| 男女做爱视频网站| 国产A片录制现场妹子都很多| 日韩成人大片| 国产青青| 人妻无码精品久久人妻成人| 99热在线只有精品| 亚洲美女视频| 成年人免费网站| 丁香五月欧美激情| 麻豆免费福利视频| 性欧美欧美巨大69| 亚洲天堂免费观看| 四川少妇bbbb| 北条麻妃中文字幕在线观看| 欧美视频一区| 日韩AV无码一区二区| 东北女人操逼| 久久露脸国语精品国产91|