Go 項目目錄結構指南

擁有一個井然有序的目錄結構非常重要,原因有幾個:

1. 常見的目錄結構

1.1 扁平結構

扁平目錄結構將所有文件直接存儲在根目錄中,沒有深層嵌套或多個子目錄。這種簡單性使得導航和管理變得容易,特別適用於小型或簡單的項目。

project/
├── main.go        # 應用程序入口點
├── handler.go     # HTTP 處理器
├── service.go     # 業務邏輯
├── repository.go  # 數據訪問
├── config.go      # 配置設置
├── utils.go       # 工具函數
├── go.mod         # Go 模塊文件
└── go.sum         # Go 模塊依賴文件

使用場景:

1.2 分層結構

在分層結構中,應用程序被組織成不同的層次,例如控制器(或處理程序)、服務、倉儲層和模型。每一層都有其特定的角色,使代碼更易於管理。

project
├── cmd                      # 與命令相關的文件
│   └── app                  # 應用程序入口點
│       └── main.go          # 主應用程序邏輯
├── internal                 # 內部代碼庫
│   ├── handlers             # HTTP 請求處理器(控制器)
│   │   └── user_handler.go  # 用戶相關的處理器
│   ├── services             # 業務邏輯(服務層)
│   │   └── user_service.go  # 用戶相關的服務
│   ├── repositories         # 數據訪問(倉儲層)
│   │   └── user_repo.go     # 用戶相關的倉儲
│   └── models               # 數據模型(實體)
│       └── user.go          # 用戶模型
├── pkg                      # 通用的工具或輔助函數
├── configs                  # 配置文件
├── go.mod                   # Go 模塊定義文件
└── go.sum                   # Go 模塊校驗和文件

使用場景:

1.3 領域驅動設計

在領域驅動設計(DDD)中,應用程序被劃分爲領域或邊界上下文,每個領域擁有自己的層,包括模型、倉儲層和服務。這種方法有助於隔離邏輯,使代碼具有領域特定性,從而促進更好的組織和清晰度。

project
├── cmd                    # 與命令相關的文件
│   └── app                # 應用程序入口點
│       └── main.go        # 主應用程序邏輯
├── internal               # 內部代碼庫
│   ├── user               # 用戶領域
│   │   ├── handler.go     # 用戶相關的處理器
│   │   ├── service.go     # 用戶相關的服務
│   │   ├── repository.go  # 用戶相關的倉儲
│   │   └── user.go        # 用戶模型
│   └── product            # 產品領域
│       ├── handler.go     # 產品相關的處理器
│       ├── service.go     # 產品相關的服務
│       └── repository.go  # 產品相關的倉儲
├── pkg                    # 通用工具
├── configs                # 配置文件
├── go.mod                 # Go 模塊定義文件
└── go.sum                 # Go 模塊校驗和文件

使用場景:

1.4 整潔架構

整潔架構將應用程序組織成不同的層,每一層的依賴關係都明確指向內層。這樣的結構確保核心業務邏輯獨立於外部系統,例如數據庫、框架或用戶界面。

project
├── cmd/                         # 與命令相關的文件
│   └── app/                     # 應用程序入口點
│       └── main.go              # 主應用程序邏輯
├── internal                     # 內部代碼庫
│   ├── delivery/                # 外部層(HTTP 處理器、gRPC 等)
│   │   └── http/                # HTTP 交付層
│   │       └── user_handler.go  # 用戶相關的 HTTP 處理器
│   ├── usecases/                # 用例(業務邏輯層)
│   │   └── user_service.go      # 用戶相關的服務邏輯
│   ├── repository/              # 倉儲層(數據訪問、外部服務)
│   │   └── user_repo.go         # 用戶相關的數據訪問邏輯
│   └── entities/                # 實體層(核心模型、領域對象)
│       └── user.go              # 用戶模型
├── pkg/                         # 通用工具或輔助函數
├── configs/                     # 配置文件
├── go.mod                       # Go 模塊定義文件
└── go.sum                       # Go 模塊校驗和文件

關鍵原則:

使用場景:

1.5 模塊化結構

模塊化結構將應用程序組織成鬆散耦合、自包含的模塊,每個模塊都有自己的代碼庫。這種方法使每個模塊能夠專注於特定的功能或業務單元,從而提高了可重用性和可擴展性。

project/
├── user_module/                  # 用戶模塊
│   ├── handler/                    # 用戶相關請求的處理器
│   ├── service/                    # 用戶操作的業務邏輯
│   ├── repository/                 # 用戶數據的數據訪問層
│   ├── user.go                     # 用戶模型定義
│   ├── go.mod                      # 用戶模塊的 Go 模塊定義文件
│   └── go.sum                      # 用戶模塊的 Go 模塊校驗和文件
├── product_module/               # 產品模塊
│   ├── handler/                    # 產品相關請求的處理器
│   ├── service/                    # 產品操作的業務邏輯
│   ├── repository/                 # 產品數據的數據訪問層
│   ├── product.go                  # 產品模型定義
│   ├── go.mod                      # 產品模塊的 Go 模塊定義文件
│   └── go.sum                      # 產品模塊的 Go 模塊校驗和文件
├── api_gateway/                  # API 網關,用於管理不同服務
│   ├── main.go                     # API 網關的主入口
│   ├── go.mod                      # API 網關的 Go 模塊定義文件
│   └── go.sum                      # API 網關的 Go 模塊校驗和文件
└── configs/                      # 共享配置文件

使用場景:

1.6 基於功能的目錄結構

在基於功能的目錄結構中,應用程序的每個功能或特性都被視爲一個獨立的單元。與該功能相關的所有代碼,包括處理器、服務、數據倉庫等,都集中放在該功能的目錄下。這種方法增強了功能內部的內聚性,並促進了功能特定邏輯的封裝。

project/
├── cmd/
│   └── app/
│       └── main.go      # 主應用邏輯
├── internal/
│   ├── user/            # 功能模塊:用戶
│   │   ├── handler/      # 用戶相關的 HTTP 處理器
│   │   ├── service/      # 用戶相關的業務邏輯
│   │   ├── repository/   # 用戶相關的數據訪問層
│   │   └── user.go       # 用戶模型
│   ├── product/         # 功能模塊:產品
│   │   ├── handler/      # 產品相關的 HTTP 處理器
│   │   ├── service/      # 產品相關的業務邏輯
│   │   ├── repository/   # 產品相關的數據訪問層
│   │   └── product.go    # 產品模型
│   ├── order/           # 功能模塊:訂單
│   │   ├── handler/      # 訂單相關的 HTTP 處理器
│   │   ├── service/      # 訂單相關的業務邏輯
│   │   ├── repository/   # 訂單相關的數據訪問層
│   │   └── order.go      # 訂單模型
├── pkg/                 # 公共工具或輔助功能
│   └── logger.go        # 日誌工具
├── configs/             # 配置文件
├── go.mod               # Go 模塊定義文件
└── go.sum               # Go 模塊依賴校驗文件

特點:

使用場景:

1.7 六邊形架構

六邊形架構,通常稱爲端口與適配器,是一種強調將核心業務邏輯與外部依賴分離的架構模式。在這種結構中,核心通過端口(即接口)與外部世界進行交互,而數據庫和網絡框架等外部系統則充當實現這些接口的適配器。

project/
├── cmd/
│   └── app/
│       └── main.go                  # 主應用邏輯
├── internal/
│   ├── core/                        # 核心業務邏輯(實體和用例)
│   │   ├── user/                    # 用戶功能模塊
│   │   │   ├── entity.go            # 用戶實體(領域對象)
│   │   │   └── usecase.go           # 業務邏輯(用例)
│   │   └── product/                 # 產品功能模塊,結構相同
│   │       └── ...                  # 產品相關文件
│   ├── adapters/                    # 實現外部系統接口的適配器
│   │   ├── database/                # 數據庫適配器(倉儲層)
│   │   │   └── user_repo.go         # 用戶倉儲實現
│   │   ├── api/                     # API 適配器(HTTP 處理器)
│   │   │   └── user_handler.go      # 用戶相關的 HTTP 處理器
│   │   └── messaging/               # 消息系統(例如 Kafka)
│   │       └── user_event.go        # 用戶事件消息處理
│   └── ports/                       # 端口(接口)
│       ├── user_repository.go       # 用戶倉儲接口
│       ├── user_service.go          # 用戶服務接口
│       └── ...                      # 其他端口接口
├── pkg/                             # 公共工具
├── configs/                         # 配置文件
├── go.mod                           # Go 模塊定義文件
└── go.sum                           # Go 模塊依賴校驗文件

特點:

使用場景:

1.8 Monorepo 結構

Monorepo 是一個包含多個服務或庫的單一代碼庫。這種結構通常在大型組織中使用,使得不同的項目可以獨立開發和部署,同時仍然位於一個統一的代碼庫中。

project/
├── services/                           # 服務目錄
│   ├── user-service/                   # 用戶服務
│   │   ├── cmd/                        # 用戶服務主應用邏輯
│   │   │   └── main.go                 # 用戶服務的主應用邏輯
│   │   ├── internal/                   # 用戶服務的內部代碼庫
│   │   │   ├── handler/                # 用戶特定的 HTTP 處理器
│   │   │   ├── service/                # 用戶特定的業務邏輯
│   │   │   ├── repository/             # 用戶特定的數據訪問
│   │   │   └── models/                 # 用戶模型
│   │   ├── go.mod                      # 用戶服務 Go 模塊定義
│   │   └── go.sum                      # 用戶服務 Go 模塊校驗和文件
│   └── product-service/                # 產品服務
│       ├── cmd/                        # 產品服務的命令相關文件
│       ├── internal/                   # 產品服務的內部代碼庫
│       └── go.mod                      # 產品服務 Go 模塊定義
├── libs/                               # 跨多個服務共享的庫
│   ├── logging/                        # 日誌庫
│   ├── authentication/                 # 認證庫
│   └── utils/                          # 工具函數
├── go.mod                              # 頂層 Go 模塊定義
└── go.sum                              # 頂層 Go 模塊校驗和文件

特點:

使用場景:

1.9 CQRS(Command Query Responsibility Segregation)

在命令查詢責任分離(CQRS)中,命令和查詢操作被組織成獨立的模型。命令負責改變狀態(例如,創建或更新數據),而查詢則專注於讀取數據。這種結構增強了處理請求時的關注點分離。

project/
├── cmd/                                # 命令目錄
│   └── app/                            # 應用程序
│       └── main.go                     # 主應用邏輯
├── internal/                           # 內部代碼庫
│   ├── commands/                       # 命令(修改狀態)
│   │   ├── create_user.go              # 創建用戶的命令
│   │   ├── update_user.go              # 更新用戶的命令
│   │   └── delete_user.go              # 刪除用戶的命令
│   ├── queries/                        # 查詢(讀取數據)
│   │   └── get_user.go                 # 獲取用戶數據的查詢
│   ├── repositories/                   # 數據訪問的倉庫
│   │   └── user_repo.go                # 用戶倉庫
│   ├── models/                         # 領域模型
│   │   └── user.go                     # 用戶領域模型
│   └── services/                       # 業務邏輯
│       └── user_service.go             # 用戶服務邏輯
├── configs/                            # 配置文件
├── go.mod                              # Go 模塊定義
└── go.sum                              # Go 模塊校驗和文件

特點:

使用場景:

1.10 洋蔥架構

洋蔥架構強調通過將代碼組織成圍繞中心核心的同心圓(或層)來實現關注點分離。最內層代表業務邏輯和領域模型,而外層則包含外部依賴,如框架、用戶界面和數據庫。

project/
├── cmd/                              # 命令目錄
│   └── your-app/                     # 應用程序
│       └── main.go                   # 應用程序入口點
├── internal/                         # 內部代碼庫
│   ├── domain/                        # 核心業務邏輯和實體
│   │   ├── entity.go                  # 領域實體
│   │   └── service.go                 # 領域服務
│   ├── application/                   # 應用服務
│   │   ├── usecase.go                 # 與領域交互的用例
│   └── infrastructure/                # 外部基礎設施
│       ├── persistence/               # 數據庫實現
│       │   ├── repository.go          # 數據庫交互的倉庫
│       ├── api/                       # Web API 層
│       │   └── handler.go             # HTTP 處理器
│       └── ...                        # 其他外部服務(消息代理等)
├── pkg/                               # 跨項目共享代碼(助手,工具)
│   └── shared/                        # 共享代碼
├── configs/                           # 配置文件(YAML,JSON 等)
│   └── config.yaml
└── go.mod                             # Go 模塊文件

特點:

使用場景:

1.11 通用架構

通用結構適用於較簡單的項目或場景,在這些情況下,開發速度和易於理解被優先考慮,而不是嚴格的架構指南。它允許靈活性,但從長遠來看可能導致代碼的可維護性降低。

project/
├── cmd/                             # 項目的主應用程序
│   └── myapp/                       # myapp 可執行文件的目錄
│       └── main.go                  # 應用程序入口點
├── internal/                        # 私有應用程序和庫代碼
│   ├── app/                         # 特定應用程序代碼
│   │   └── myapp/                   # myapp 的應用程序代碼
│   │       ├── handler.go           # HTTP 處理器
│   │       └── service.go           # 業務邏輯
│   ├── pkg/                         # 共享的內部代碼(私有庫)
│   │   └── myprivlib/               # 內部使用的共享庫
│   ├── domain/                      # 領域模型和服務
│   │   ├── entity.go                # 領域實體
│   │   └── service.go               # 領域服務
│   └── infrastructure/              # 外部基礎設施代碼
│       ├── persistence/             # 數據庫實現
│       │   └── repository.go        # 數據庫交互的倉庫
│       ├── api/                     # Web API 層
│       │   └── handler.go           # API 處理器
│       └── messaging/               # 消息系統(如 Kafka)
│           └── producer.go          # 消息生產者
├── pkg/                             # 對外使用的庫代碼
│   └── mypubliclib/                 # 對外的公共庫
├── vendor/                          # 應用程序依賴
├── api/                             # OpenAPI/Swagger 規範,JSON 架構文件
│   └── api_spec.yaml                # API 規範文件
├── web/                             # Web 應用程序組件
│   ├── static/                      # 靜態資源(CSS,JS)
│   └── templates/                   # 服務器端模板
├── configs/                         # 配置文件
│   └── config.yaml                  # 默認配置
├── init/                            # 系統初始化配置
│   └── myapp.service                # Systemd 服務文件
├── scripts/                         # 構建、安裝、分析腳本
│   ├── build.sh                     # 構建腳本
│   └── install.sh                   # 安裝腳本
├── build/                           # 打包和 CI 配置
│   ├── package/                     # 打包配置(Docker,AMI 等)
│   └── ci/                          # CI 配置(Travis,CircleCI)
├── deployments/                     # 部署配置和模板
│   └── kubernetes/                  # Kubernetes 部署配置
├── test/                            # 額外的外部測試應用和數據
│   └── data/                        # 測試數據
├── docs/                            # 設計和用戶文檔
│   └── architecture.md              # 項目架構文檔
├── tools/                           # 支持項目的工具
│   └── mytool/                      # 示例工具目錄
├── examples/                        # 應用程序和庫的示例
│   └── example_usage.go             # 公共庫的示例用法
├── third_party/                     # 外部輔助工具和實用程序
├── githooks/                        # Git hooks
├── assets/                          # 其他資產(圖片,LOGO)
├── website/                         # 項目網站數據
│   └── index.html                   # 項目的首頁
├── go.mod                           # Go 模塊文件
└── go.sum                           # Go 模塊依賴文件

特點:

使用場景:

2. 結語

選擇合適的目錄結構至關重要,但是這取決於你當前的需求,比如程序大小,複雜性,團隊大小,可維護性等等。

通常,選擇一個滿足當前需求的結構就可以,隨着項目的發展或需求的變化可以進行重構。

但從實際工作的角度看,如果處在一個長期需求維護的項目團隊時,建議選擇可維護性,可擴展性,職責分離明確的目錄結構更好。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/8nuxeGruMZAC2nKIB0p8Kg