Go | 避免常見套件設計陷阱
💬 簡介
在 Go 語言中,套件(package)是實現模組化與高可維護性的核心單位。
但若設計不當,套件反而會變成系統的負擔:無窮的相依、無謂的公開函式、混亂的目錄結構……
本篇將彙整套件設計中常見的錯誤模式與解法,幫助你從源頭就「防患未然」。
圖片來源:Gophers
❌ 常見設計陷阱與誤區
1️⃣ 過度耦合(Tightly Coupled Packages)
每個套件都互相 import,導致無法重構或單元測試。
錯誤示範:
1 | // user.go |
改進建議:
- ✅ 使用介面抽象跨層級相依
- ✅ 引入第三方 service 或 repository 層解耦邏輯
1 | // 定義依賴介面 |
2️⃣ 所有功能塞一包(God Package)
一個套件內放了所有邏輯,變成「胖套件」,難以維護。
錯誤示範:
1 | // utils.go 裡面含有:資料庫、編碼、驗證、日期處理…… |
改進建議:
- ✅ 按職責切分為子套件:
db/
、encode/
、validate/
… - ✅ 每個子套件只關心一件事(Single Responsibility)
3️⃣ 不當的公開範圍
為了「方便呼叫」而把所有函式與變數都大寫導出。
錯誤示範:
1 | var ConfigMap map[string]string // 外部可自由修改 ConfigMap |
改進建議:
- ✅ 僅導出真正需對外使用的函式與類型
- ✅ 私有邏輯使用小寫開頭封裝
1 | var configMap map[string]string // 小寫封裝 |
4️⃣ 循環引用(Import Cycle)
兩個套件互相 import,導致編譯失敗。
錯誤示範:
1 | // a.go |
改進建議:
- ✅ 將共用邏輯抽出到第三方套件(如
common/
) - ✅ 使用 interface 分離依賴方向
5️⃣ 不穩定的相依鏈(Unstable Dependencies)
套件層級混亂,高階邏輯 import 低階細節,難以重構。
解法參考:
- ✅ 高層模組依賴介面,而非具體實作
- ✅ 套件之間依賴方向需符合資料流與控制流設計
ℹ️ 實務設計守則總結
原則 | 說明 |
---|---|
小而專注(SRP) | 每個套件只做一件事 |
封裝私有細節 | 善用小寫封裝實作 |
導出穩定、明確的 API | 避免破壞變更 |
避免循環與雙向依賴 | 引入中介層或介面拆分 |
按需求做目錄與子套件設計 | 避免先分再用的過早切割 |
🔀 範例重構前後比對
原始套件(耦合混亂):
1
2
3
4/app/
|- handler.go // 控制器直接使用資料庫
|- db.go // 直接暴露 *sql.DB
|- util.go // 各種工具混雜改進後套件(清晰職責):
1
2
3
4
5/app/
|- handler/ // 負責接收請求與輸出結果
|- service/ // 處理邏輯與商業規則
|- repository/ // 資料存取
|- common/ // 共用常數與工具
🎯 總結
設計良好的套件架構是可維護系統的基石。避免常見錯誤可以讓你的專案更具彈性與可讀性:
- ✅ 切分責任清楚,避免「神級套件」
- ✅ 控制對外公開範圍,封裝內部實作
- ✅ 使用 interface 解耦與避免循環依賴
- ✅ 遵循穩定依賴原則與良好套件命名
最後建議回顧一下 Go | 菜鳥教學 目錄,了解其章節內容。
註:以上參考了
Go