Go | 套件結構介面協同設計
💬 簡介
隨著程式規模擴大,設計良好的模組結構與職責劃分變得越來越重要。Go 雖然以簡潔著稱,但仍能藉由結構體與介面的設計,配合套件拆分,達到清楚的模組邊界與低耦合的維護策略。
本篇將介紹:
- 結構體與介面的協同設計概念
- 如何設計內聚的套件
- 實現鬆耦合的模組分層架構
圖片來源:Gophers
🧩 結構體與介面協同設計的原則
🧱 高內聚:功能集中且清晰
每個套件應集中於單一領域邏輯,例如:user
處理用戶邏輯auth
處理驗證邏輯store
處理資料存取
🔗 低耦合:依賴抽象、隔離實作
透過定義介面(interface),讓模組依賴行為定義而非具體實作。這樣可在不改動呼叫方邏輯的情況下替換實作內容。
📦 範例:使用者系統設計
🛠️ 結構化的套件設計
1
2
3
4
5
6
7
8project/
├── main.go
├── user/
│ ├── service.go
│ └── model.go
├── store/
│ ├── user_store.go
│ └── memory_store.go📄 定義使用者結構體與介面
user/model.go
:1
2
3
4
5
6
7package user
type User struct {
ID int
Name string
Email string
}user/service.go
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22package user
type Store interface {
GetByID(id int) (*User, error)
Save(u *User) error
}
type Service struct {
store Store
}
func NewService(s Store) *Service {
return &Service{store: s}
}
func (s *Service) GetUser(id int) (*User, error) {
return s.store.GetByID(id)
}
func (s *Service) CreateUser(u *User) error {
return s.store.Save(u)
}📝 使用介面
Store
隔離資料存取邏輯,Service
專注業務邏輯,符合高內聚。🗃️ 實作資料存取層
store/user_store.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
27package store
import (
"errors"
"project/user"
)
type InMemoryUserStore struct {
data map[int]*user.User
}
func NewInMemoryUserStore() *InMemoryUserStore {
return &InMemoryUserStore{data: make(map[int]*user.User)}
}
func (s *InMemoryUserStore) GetByID(id int) (*user.User, error) {
u, ok := s.data[id]
if !ok {
return nil, errors.New("找不到用戶")
}
return u, nil
}
func (s *InMemoryUserStore) Save(u *user.User) error {
s.data[u.ID] = u
return nil
}🚀 使用方式:main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22package main
import (
"fmt"
"project/store"
"project/user"
)
func main() {
userStore := store.NewInMemoryUserStore()
userService := user.NewService(userStore)
newUser := &user.User{ID: 1, Name: "小明", Email: "ming@example.com"}
_ = userService.CreateUser(newUser)
u, err := userService.GetUser(1)
if err != nil {
fmt.Println("錯誤:", err)
return
}
fmt.Printf("取得用戶:%+v\n", u)
}
🧠 設計思維補充
原則 | 說明 |
---|---|
Interface as contract | 介面定義代表行為契約,有利於替換與測試 |
Dependency Injection | 將實作注入(如 store ),避免 Service 綁死具體實作 |
Package boundaries | 模組依功能拆分(業務邏輯 / 資料存取 / 結構定義),保持清晰的職責劃分 |
🧪 測試與擴充性
由於使用介面注入,你可以很容易撰寫測試:
1 | type fakeStore struct {} |
📝 單元測試可使用假實作來隔離依賴。
🎯 總結
將結構體與介面結合應用於套件設計,不但能保持程式邏輯清晰、可測、易維護,也有助於團隊協作與模組擴充。
本篇重點如下:
- ✅ 使用介面隔離實作,促進低耦合設計
- ✅ 套件應聚焦單一職責,促進高內聚
- ✅ 配合結構化目錄與依賴注入,實現可擴充模組
最後建議回顧一下 Go | 菜鳥教學 目錄,了解其章節內容。
註:以上參考了
Go