經(jīng)過(guò)這些年的發(fā)展,Go語(yǔ)言已經(jīng)成為一門(mén)被廣泛使用在各個(gè)領(lǐng)域的編程語(yǔ)言。從k8s、docker等基礎(chǔ)組件,到業(yè)務(wù)領(lǐng)域的微服務(wù),都可以用Go構(gòu)建。在構(gòu)建這些Go項(xiàng)目時(shí),采用哪種架構(gòu)模式和代碼布局,是一個(gè)仁者見(jiàn)仁智者見(jiàn)智的事情。有Java Spring經(jīng)驗(yàn)的可能會(huì)采用MVC模式,有Python Flask經(jīng)驗(yàn)的可能會(huì)采用MTV模式。加上Go語(yǔ)言領(lǐng)域并沒(méi)有出現(xiàn)主流的企業(yè)級(jí)開(kāi)發(fā)框架,很多項(xiàng)目甚至沒(méi)有明確的架構(gòu)模式。
Clean Architecture

Clean Architecture是Uncle Bob提出的適用于復(fù)雜業(yè)務(wù)系統(tǒng)的架構(gòu)模式,其核心思想是將業(yè)務(wù)復(fù)雜度與技術(shù)復(fù)雜度解藕,相比于MVC、MTV等模式,Clean Architecture除了進(jìn)行分層,還通過(guò)約定依賴(lài)原則,明確了與外部依賴(lài)的交互方式,以及外部依賴(lài)與業(yè)務(wù)邏輯的邊界。感興趣的朋友可以直接閱讀作者原文https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html。
由于Clean Architecture具有脫離語(yǔ)言和框架的靈活性,作者在提出時(shí)也沒(méi)有規(guī)定實(shí)現(xiàn)細(xì)節(jié),給Clean Architecture的落地帶來(lái)了困難,接下來(lái)以一個(gè)例子來(lái)說(shuō)明如何在Go項(xiàng)目中應(yīng)用Clean Architecture的思想。
布局
作為一個(gè)Go項(xiàng)目,不管用哪種架構(gòu)模式,建議都建立app和scripts這兩個(gè)路徑。app存放啟動(dòng)Go項(xiàng)目的入口文件,通常是main.go。而scripts可以放一些構(gòu)建和部署時(shí)候用到的腳本。
clean_architecture_demo
├── README.md
├── app
│ └── main.go
├── scripts
│ ├── build.sh
│ └── run.sh
├── go.mod
├── go.sum
└── usecases
接下來(lái)是代碼部分,分為entities、usecases、adapters三個(gè)部分。
- entities:存儲(chǔ)領(lǐng)域?qū)嶓w。用一個(gè)博客系統(tǒng)舉例,領(lǐng)域?qū)嶓w可能有用戶(hù)(user)和文章(article)
- usecases:存儲(chǔ)業(yè)務(wù)邏輯。用博客系統(tǒng)舉例,可能會(huì)有用戶(hù)相關(guān)的業(yè)務(wù)邏輯(signup_user、signin_user、add_user、delete_user)和文章相關(guān)的業(yè)務(wù)邏輯(add_article、show_article、delete_article)
- adapters:存儲(chǔ)適配器邏輯。適配器是連接業(yè)務(wù)邏輯與外部依賴(lài)的層,博客以Web形式提供服務(wù),就需要一個(gè)http_adapter來(lái)封裝Web服務(wù);同時(shí)保存文章到數(shù)據(jù)庫(kù),需要封裝一個(gè)db_adapter來(lái)連接。
下面是項(xiàng)目的布局結(jié)構(gòu)。
clean_architecture_demo
├── README.md
├── adapters
│ ├── api
│ ├── db
│ └── log
├── app
│ └── main.go
├── scripts
│ ├── build.sh
│ └── run.sh
├── entities
│ ├── article.go
│ └── user.go
├── go.mod
├── go.sum
└── usecases
數(shù)據(jù)流向
用一個(gè)查詢(xún)文章的請(qǐng)求來(lái)描述一下調(diào)用鏈路。
- 用戶(hù)通過(guò)HTTP服務(wù)的調(diào)用WebAdapter的ShowArticleHandler方法
- 由于是文章相關(guān)的邏輯,ShowArticleHandler調(diào)用ArticleUsecase的ShowArticle方法
- 需要從DB中查詢(xún)文章,ArticleUsecase會(huì)調(diào)用DBAdapter的GetArticle方法
- DBAdapter的GetArticle從MySQL中查詢(xún)出文章內(nèi)容返回給ArticleUsecase
- ArticleUsecase返回給WebAdapter
- WebAdapter通過(guò)HTTP服務(wù)返回給用戶(hù)

代碼示例
為了更清晰的說(shuō)分層和架構(gòu),我在Github上發(fā)布了一個(gè)示例項(xiàng)目,感興趣的朋友可以直接去看源碼:https://github.com/simpleapples/go-clean-architecture
結(jié)論
由于Clean Architecture沒(méi)有規(guī)定實(shí)現(xiàn)細(xì)節(jié),所以上述的分層和布局方式只是一種參考,還有眾多的實(shí)踐方式。例如Adapter層可以根據(jù)外部依賴(lài)的類(lèi)型細(xì)分成平行的Presenter+Gateway層,在復(fù)雜項(xiàng)目中,更細(xì)致的分層可以把代碼拆的更細(xì)致,大家可以根據(jù)自己的項(xiàng)目規(guī)模來(lái)調(diào)整分層和布局,這里就不做贅述了。