為什麼要先規劃目錄結構
剛開始寫 Go 項目的時候,我對目錄結構這件事格外重視。對於剛入門的人來説,開發過程中幾乎每件事情都是第一次:
- 全局配置怎麼放?
- 數據庫連接怎麼初始化?
- Model 怎麼設計?
- 路由怎麼組織?
每一個點都能讓人迷茫。
相比之下,像 Java 的 Spring Boot 或 PHP 的 Laravel 都會給你一套“默認結構”,至少能讓你知道應該往哪裏放東西。
而 Go 更自由,沒有強迫你必須怎麼做。對老手是好事,對新手卻可能會踩坑。
我的經驗是:
合理的目錄結構 = 清晰的思路 + 舒適的開發體驗
規劃好結構之後,你可以把問題拆開逐個去實現,而不是一上來就面對一坨混亂的代碼。
我的 Go 項目目錄結構(Gin 示例)
下面是我常用的目錄結構,適合大多數中小型 Web 項目:
.
├── cmd/ # 項目入口目錄
│ └── main.go # 主程序入口
├── internal/ # 私有代碼目錄
│ ├── dto/ # 結構體定義目錄
│ ├── handler/ # HTTP處理器(等同於Controller)
│ ├── model/ # 數據模型
│ ├── repository/ # 數據模型訪問層
│ ├── router/ # 路由
│ └── service/ # 業務邏輯層
├── pkg/ # 可被外部引用的包
│ ├── config/ # 配置
│ ├── i18n/ # 國際化
│ ├── jwt/ # jwt
│ ├── middleware/ # 中間件
│ └── utils/ # 工具函數
├── api/ # API文檔(Swagger)
│ └── swagger.json
├── scripts/ # 構建、部署腳本目錄
├── go.mod
├── LICENSE
├── Makefile # 自動化腳本説明書
└── README.md
cmd/:項目入口
cmd 存放整個項目的入口程序。
通常項目只有一個:
cmd/
└── main.go
如果未來拆成多個服務(如 API + Worker),結構可以擴展成:
cmd/
├── api/
│ └── main.go
├── worker/
│ └── main.go
這樣多服務更好管理。
internal/:項目私有代碼
internal 是 Go 官方定義的 私有代碼機制:這裏的包只能本項目引用,外部無法導入。
我會把它拆成幾個層次,職責分明:
internal/
├── dto/ # 請求/響應結構體
├── handler/ # HTTP 層
├── service/ # 業務邏輯層
├── repository/ # 數據訪問層
├── model/ # 數據模型
└── router/ # 路由註冊
調用鏈是單向的:
Handler → Service → Repository → Model
下面簡單説一下每層負責什麼:
- Handler:接收/解析請求,參數校驗,調用 Service
- Service:業務邏輯處理
- Repository:數據庫讀寫(純 CRUD,不寫業務)
- Model:數據庫結構體
- DTO:請求/響應結構(隔離 Model)
- Router:註冊路由,綁定 Handler
這種分層結構很適合 Go,也比 PHP 那種“一個 controller 幹到底”的寫法更好維護。
另外,Go 的一個特點是:
同一個 package 下多個 .go 文件對編譯器來説等同於同一個文件。
所以可以自由地按模塊拆成多個 user.go、order.go,對程序來説他們直接就是一個文件不會有任何影響,但分開之後代碼的可讀性會極大的提高。
如果你有其他面嚮對象語言的經驗,Go會帶來全新的編程體驗。核心的思維轉變可歸納為四點:
- 忘掉"類" → 記住"結構體+方法"
- 忘掉"繼承" → 使用"組合+接口"
- 忘掉"設計模式套用" → 關注"解決問題"
- 接受顯式錯誤處理 → 不再有try-catch
pkg/:可複用的公共包
pkg 用來放可被其他項目引用的通用模塊,例如:
pkg/
├── config/
├── i18n/
├── jwt/
├── middleware/
└── utils/
如果只是給當前項目用,不需要放在 pkg,儘量歸到 internal。
另外也建議不要堆一個“大 utils”,按功能拆分更容易維護。
api/:API 文檔
這裏一般放 Swagger / OpenAPI 的定義文件(JSON/YAML)。
用這些工具來管理接口文檔可以:
- 自動生成文檔
- 保持前後端對齊
對於多人協作非常有用。
Makefile:常用命令的“快捷鍵”
我一般會把常用命令寫進 Makefile,比如:
run:
go run cmd/main.go
build:
go build -o bin/app cmd/main.go
test:
go test ./...
Makefile 是個好東西,你可以把各種項目會用到的命令像清單一樣列出來。
如果你有心思,甚至可以去做一個 help 命令來告訴其他人都有什麼命令
help:
@echo "可用指令:"
@echo " make deps # 安裝 / 更新 Go 依賴"
@echo " make fmt # 統一格式化後端 Go 代碼"
@echo " make test # 執行全部 Go 單元測試"
對新同事非常友好,哪怕不瞭解項目,也可以通過閲讀 Makefile 快速上手項目。
總結
對我來説,一旦目錄結構定下來,剩下的基本就像做“填空題”一樣:
- 中間件怎麼寫
- JWT 怎麼做
- 數據庫要建哪些表
- Handler / Service / Repository 各自實現哪些邏輯
這些都能一塊一塊穩穩推進。
Go 社區裏沒有唯一正確的結構,但這套分層思路對新手來説非常友好,也足夠應對大部分項目。
如果你正在準備寫一個 Go 項目,希望這套結構能幫你少踩一些坑,也讓你的項目更容易維護。