Go 語言編程 — 項目布局規范
目錄
文章目錄
目錄
項目布局(Project Layout)規范
程序目錄
/cmd(Command)包
/internal
/pkg(Package)
/vendor
Service(服務端)應用目錄
/api
Web 應用目錄
/web
常規目錄
/configs
/init
/scripts
/build
/deployments
/test
Makefile
/docs
/tools
/examples
/third_party
/githooks
/assets
/website
不建議使用的目錄
/src
適用于框架或庫的平鋪布局
項目布局(Project Layout)規范
類似于 Python 的 Module,Golang 對于模塊的劃分是基于 Package 這個概念,一個文件就可以是一個 Package(通過 package 語句)。也就是說,在一個目錄中可以實現多個 Packages。但實際上并不建議這樣的實現方式,主要的缺點是模塊之間的關系不清晰,另外也不利于模塊功能擴展。所以,推薦的是將一個目錄定位一個 Package,一個 Package(目錄)下屬存在多個代碼文件。
注意,Golang 項目中,一個 Package 建議是一個目錄,一個目錄不一定是一個 Package。
基于此,Golang 項目的布局應該遵循一定的規范。官方標準:https://github.com/golang-standards/project-layout
注意:本文列舉的目錄為項目頂層子目錄清單。
├── .gitignore ├── LICENSE.md ├── Makefile ├── README.md ├── go.mod ├── api ├── assets ├── build ├── cmd ├── configs ├── deployments ├── docs ├── examples ├── githooks ├── init ├── internal ├── pkg ├── scripts ├── test ├── third_party ├── tools ├── vendor ├── web └── website
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
程序目錄
/cmd(Command)包
存放項目下屬的若干個程序的可執行文件,也就是程序入口文件(e.g. /cmd/app/main.go)。
參考:https://github.com/golang-standards/project-layout/blob/master/cmd/README.md
cmd 包下的每個程序的目錄名應該和程序的可執行文件名保持一致。
通常的,程序的 main() 函數不宜編寫太多松散的代碼。
/internal
存放項目 “內部” 代碼。即:當前項目內部(Internal)私有的程序和庫代碼。
放在 internal 包的代碼表明只希望在項目內部使用,當我們在其他項目中的程序導入來自 internal 包的依賴時,Golang 會在編譯時報錯:
An import of a path containing the element “internal” is disallowed if the importing code is outside the tree rooted at the parent of the "internal" directory.
1
2
注意,internal 包不是必需的(尤其是對于較小的項目),但最好有視覺提示來顯示該目錄的含義。在 internal 包中,還可以考慮添加一些額外的目錄樹結構,以分隔共享和非共享內部代碼。例如:實際應用程序代碼可以存放在 /internal/app 子目錄下,而這些應用程序共享的代碼可以存放在 /internal/pkg 子目錄和 /pkg 中。
/pkg(Package)
存放 “公共” 代碼。
所謂 “公共” 就是可以被其他的項目引用。
通常的,pkg 包的代碼應該與具體的業務無關,具有高度通用性的抽象,以方便本項目和其他項目重用。其作用類似于 C 語言中的庫文件。當我們使用 go install 安裝項目的時候,會將代碼編譯成 .a 靜態庫文件。
當你決定將代碼放入 pkg 包時,你應該對其負責,因為其他項目中的程序可以通過 import 來導入這里的代碼。所以當我們將代碼放入 pkg 包時一定要慎重,考慮清楚這些代碼是否應該被 “公開”。
/vendor
存放程序的外部依賴??梢允止す芾恚部梢允褂?Golang 提供的 dep 工具(https://github.com/golang/dep)或者 glide(https://github.com/Masterminds/glide)工具。
在 Go 1.13 版本啟用了 go module 來代替,并不需要 /vendor 目錄了。
Service(服務端)應用目錄
/api
存放項目對外提供的若干個北向 API 接口的定義文件。包括:OpenAPI/Swagger 的規范(Specs)文件、JSON schema 文件,以及協議定義文件。例如: /api/protobuf-spec、/api/thrift-spec 或者 /api/http-spec 目錄,這些目錄中包含了當前項目對外提供的和依賴的所有 API 文件:
$ tree ./api api └── protobuf-spec └── oceanbookpb ├── oceanbook.pb.go └── oceanbook.proto
1
2
3
4
5
6
其中,創建 oceanbookpb 二級目錄的主要作用在于一個項目同時提供了多種不同的訪問方式時,這樣可以避免潛在的沖突問題,也更加清晰。
參考:https://github.com/golang-standards/project-layout/blob/master/api/README.md
Web 應用目錄
/web
存放 Web 應用的標準組件:
靜態 Web 資源
服務端模板
單頁應用
常規目錄
/configs
存放配置文件的模板(e.g. consul-template)或者默認配置文件(e.g. confd)。
/init
存放系統初始化或自動啟動腳本(e.g. systemd、upstart、sysv),以及存放進程管理或監控程序的配置文件(e.g. runit、supervisord)。
/scripts
存放執行各種構建、安裝、分析等,或者其他操作的腳本文件。
參考:https://github.com/golang-standards/project-layout/blob/master/scripts/README.md
/build
存放打包及持續集成所需要的的文件。
將 cloud(AMI)、container(Docker)、OS(deb、rpm、pkg)軟件包的配置放在 /build/package 目錄下。
將 CI(travis、circle、drone)系統的配置和腳本放在 /build/ci 目錄下。需要注意的是,有些 CI 工具(e.g. Travis CI)對它們的配置文件的位置非常敏感。此時,我們可以把配置文件放在 /build/ci 目錄下,然后將它們軟鏈接到 CI 工具希望它們出現的位置路徑。
/deployments
存放 IaaS、PaaS、系統,以及容器編排的部署配置文件和模板文件。例如:docker-compose、kubernetes/helm、mesos、terraform、bosh 等。
/test
存放除了單元測試、基準測試之外的測試文件,例如:集成測試、測試數據等。
對于大型的項目則有必要包含一個 /test/data 子目錄,Golang 會忽略其中的某些內容。例如:/test/data 或者 /test/testdata 目錄。
注意,Golang 還會忽略任何以 “.” 和 “_” 開頭的文件和目錄。
參考:https://github.com/golang-standards/project-layout/blob/master/test/README.md
Makefile
Makefile 定義了項目編譯的細節,并且 /scripts 目錄下的腳本文件通常由 Makefile 觸發。
/docs
存放除了使用 godc 自動生成的程序文檔文件之外的文檔資料,例如:用戶及設計文檔。
參考:https://github.com/golang-standards/project-layout/blob/master/docs/README.md
/tools
存放項目需要工具集。這些工具可以導入 /pkg 和 /internal 目錄下的代碼。
參考:https://github.com/golang-standards/project-layout/blob/master/tools/README.md
/examples
存放程序示例文件。
參考:https://github.com/golang-standards/project-layout/blob/master/examples/README.md
/third_party
存放第三方輔助工具、forked 代碼。例如:Swagger UI。
/githooks
存放 Git books 文件。
/assets
存放其他資產(assets)文件,通常是圖片、logo 等文件。
/website
如果不使用 Github Pages(Github 網頁)的話,可以在 /website 放置項目的網站文件。通常是用于項目宣傳和展示的網站資料。
參考:https://github.com/golang-standards/project-layout/blob/master/website/README.md
不建議使用的目錄
/src
注意,這里所說的 /src 目錄指的是 “項目頂層” 的 /src,而不是 “Go workspace” 的 /src 目錄。
$GOPATH 環境變量指向當前環境中的 Go workspace,如果想要讓代碼運行,就需要將項目的代碼放到 workspace 下。在 UNIX-like 操作系統中通常是 $HOME/go,筆者的配置為:
$ go env | grep PATH GOPATH="/Users/mickeyfan/workspace/go"
1
2
這個 workspace 的頂層包括了 /pkg、/bin 和 /src 目錄,Golang 項目在默認情況下都會被放置到 $GOPATH/src 目錄下,存儲著我們開發和依賴的全部項目代碼。
所以,如果我們在實際項目的頂層定義了 /src 目錄,那么該項目的 $GOPATH 中就會出現兩個 src,e.g.
/some/path/to/workspace/src/your_project/src/your_code.go。
1
所以,不建議在項目的頂層創建 /src 子目錄,區別于 JAVA 的編程習慣。
適用于框架或庫的平鋪布局
當我們希望在項目中導入一個采用了 pkg 布局方式的框架時,我們往往需要使用 github.com/draveness/project/pkg/somepkg 的路徑;而當我們導入一個采用了平鋪布局方式的框架時,只需要使用 github.com/draveness/project 路徑,很明顯地減少了引用依賴包語句的長度。
所以,對于一個 Golang 的框架或者庫而言,將代碼平鋪在其根目錄下也很正常,但在一個常規的 Golang 后端項目中就不是那么合適了。
API Go
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。