Like Share Discussion Bookmark Smile

J.J. Huang   2025-07-08   Getting Started Golang 07.套件   瀏覽次數:次   DMCA.com Protection Status

Go | 重構專案優化套件結構

💬 簡介

隨著專案逐漸擴大,原本單純的程式碼架構往往變得複雜、難以維護。這時,透過重構專案套件結構,能有效提升程式碼的模組性、可讀性與可擴展性。

本文將以實務範例為出發點,說明如何系統性重構套件組織,從雜亂無章到井然有序,達成高可維護、高可復用的架構目標。

圖片來源:Gophers


💡 初始專案架構(Before)

我們以一個簡單的 TODO 管理系統為例,初始結構如下:

1
2
3
4
5
6
todo-app/
├── main.go
├── handlers.go
├── db.go
├── models.go
├── utils.go

🧨 問題點分析

  • 所有程式碼集中在同一層,缺乏模組邊界
  • handler、DB、model 等職責混合,不利單元測試與維護。
  • 新功能加入容易造成程式碼膨脹。

🛠️ 重構目標

  • 建立清晰職責分工,套件各司其職
  • 模組化程式碼結構,便於測試與重用
  • 提升未來擴充與維護的彈性

📦 重構後套件架構(After)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
todo-app/
├── cmd/
│ └── main.go
├── api/
│ ├── handler/
│ │ └── todo_handler.go
│ └── middleware/
│ └── auth.go
├── service/
│ └── todo_service.go
├── repository/
│ └── todo_repo.go
├── model/
│ └── todo.go
├── config/
│ └── config.go
├── internal/
│ └── validator.go
├── utils/
│ └── logger.go
├── go.mod

🔍 套件職責說明

套件 功能描述
cmd/ 應用程式進入點(main function)
api/ HTTP 層,處理路由、請求與 middleware
service/ 業務邏輯層,封裝實際處理流程
repository/ 資料存取層,處理 DB 操作
model/ 資料結構定義(DTO、Entity)
config/ 設定管理,如環境變數與檔案解析
internal/ 封裝內部工具,如驗證邏輯
utils/ 通用工具(Log、加密等)

🧩 重構實作範例

🌐 handler 層(api/handler/todo_handler.go)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package handler

import (
"net/http"
"todo-app/service"

"github.com/gin-gonic/gin"
)

func CreateTodo(c *gin.Context) {
var input struct {
Title string `json:"title"`
}

if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid input"})
return
}

err := service.CreateTodo(input.Title)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}

c.Status(http.StatusCreated)
}

🔧 service 層(service/todo_service.go)

1
2
3
4
5
6
7
package service

import "todo-app/repository"

func CreateTodo(title string) error {
return repository.InsertTodo(title)
}

🗄️ repository 層(repository/todo_repo.go)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package repository

import (
"database/sql"
_ "github.com/mattn/go-sqlite3"
)

var db *sql.DB

func InitDB() {
db, _ = sql.Open("sqlite3", "todo.db")
}

func InsertTodo(title string) error {
_, err := db.Exec("INSERT INTO todos (title) VALUES (?)", title)
return err
}

🧼 小步重構建議

  1. 從職責分離開始:先將 handler、model、repository 拆出來。
  2. 不急著完美化:每次 refactor 改動一層或一個模組。
  3. 建立測試基礎:重構過程中同步撰寫測試,避免破壞原邏輯。
  4. 命名與文件同步更新:避免 refactor 完卻留下過時命名與註解。

📈 重構後效益

  • 📦 各模組責任清晰,團隊協作明確
  • 🧪 測試更容易編寫與維護
  • 🛠️ 新功能加入更彈性,不會污染原有邏輯
  • 🔍 錯誤定位迅速,除錯更有依據

🎯 總結

重構不是為了改架構而改,而是為了讓程式碼更可維護、可擴展、可理解。特別在開發持續成長的專案中,建立清晰且穩健的套件架構,是團隊長期穩定發展的關鍵。

重構關鍵原則如下:

  • ✅ 明確職責分層,避免跨層耦合
  • ✅ 將應用層與業務邏輯層分離
  • ✅ 將 repository 以介面抽象,便於測試與替換
  • ✅ 保持套件邊界清晰,便於日後拆解與模組化

最後建議回顧一下 Go | 菜鳥教學 目錄,了解其章節內容。


註:以上參考了
Go