设计模式:Go 语言中的实践
设计模式是软件开发中经过验证的解决方案。它们不是具体的代码,而是一种思路,帮助你解决特定场景下的常见问题。
但是,不同的语言有不同的特性,设计模式的实现方式也会有所不同。Go 语言没有类、继承、泛型(1.18 之前),这让很多传统的面向对象设计模式需要"Go 化"。
今天我们就来学习如何在 Go 中实现常用的设计模式,用 Go 的方式写出优雅的代码。
创建型模式
单例模式(Singleton)
确保一个类只有一个实例,并提供一个全局访问点。
在 Go 中,通常使用 sync.Once 来实现:
package main
import (
"fmt"
"sync"
)
type Database struct {
conn string
}
var (
instance *Database
once sync.Once
)
func GetDatabase() *Database {
once.Do(func() {
fmt.Println("创建数据库实例...")
instance = &Database{
conn: "mysql://localhost:3306/mydb",
}
})
return instance
}
func (db *Database) Query(sql string) {
fmt.Printf("执行查询: %s\n", sql)
}
func main() {
db1 := GetDatabase()
db2 := GetDatabase()
// 两次调用返回同一个实例
fmt.Println(db1 == db2) // true
db1.Query("SELECT * FROM users")
db2.Query("SELECT * FROM posts")
}
输出:
创建数据库实例...
true
执行查询: SELECT * FROM users
执行查询: SELECT * FROM posts
“创建数据库实例…” 只打印了一次,说明 sync.Once 确保了初始化只执行一次。
工厂模式(Factory)
定义一个创建对象的接口,让子类决定实例化哪个类。
在 Go 中,没有继承,我们用接口 + 工厂函数来实现:
package main
import "fmt"
// Payment 支付接口
type Payment interface {
Pay(amount float64) error
}
// Alipay 支付宝支付
type Alipay struct{}
func (a *Alipay) Pay(amount float64) error {
fmt.Printf("使用支付宝支付 %.2f 元\n", amount)
return nil
}
// WechatPay 微信支付
type WechatPay struct{}
func (w *WechatPay) Pay(amount float64) error {
fmt.Printf("使用微信支付 %.2f 元\n", amount)
return nil
}
// BankCard 银行卡支付
type BankCard struct{}
func (b *BankCard) Pay(amount float64) error {
fmt.Printf("使用银行卡支付 %.2f 元\n", amount)
return nil
}
// PaymentFactory 支付工厂
type PaymentFactory struct{}
func (f *PaymentFactory) CreatePayment(method string) (Payment, error) {
switch method {
case "alipay":
return &Alipay{}, nil
case "wechat":
return &WechatPay{}, nil
case "bankcard":
return &BankCard{}, nil
default:
return nil, fmt.Errorf("不支持的支付方式: %s", method)
}
}
func main() {
factory := &PaymentFactory{}
// 用户选择支付方式
payment, err := factory.CreatePayment("alipay")
if err != nil {
fmt.Println("创建支付失败:", err)
return
}
payment.Pay(100.50)
}
建造者模式(Builder)
将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
package main
import "fmt"
// HTTPRequest HTTP 请求
type HTTPRequest struct {
Method string
URL string
Headers map[string]string
Body string
Timeout int
}
// RequestBuilder 请求构建器
type RequestBuilder struct {
request *HTTPRequest
}
func NewRequestBuilder() *RequestBuilder {
return &RequestBuilder{
request: &HTTPRequest{
Headers: make(map[string]string),
Timeout: 30,
},
}
}
func (b *RequestBuilder) Method(method string) *RequestBuilder {
b.request.Method = method
return b
}
func (b *RequestBuilder) URL(url string) *RequestBuilder {
b.request.URL = url
return b
}
func (b *RequestBuilder) Header(key, value string) *RequestBuilder {
b.request.Headers[key] = value
return b
}
func (b *RequestBuilder) Body(body string) *RequestBuilder {
b.request.Body = body
return b
}
func (b *RequestBuilder) Timeout(timeout int) *RequestBuilder {
b.request.Timeout = timeout
return b
}
func (b *RequestBuilder) Build() *HTTPRequest {
return b.request
}
func main() {
// 使用链式调用构建请求
req := NewRequestBuilder().
Method("POST").
URL("https://api.example.com/users").
Header("Content-Type", "application/json").
Header("Authorization", "Bearer token123").
Body(`{"name":"张三","age":25}`).
Timeout(60).
Build()
fmt.Printf("Method: %s\n", req.Method)
fmt.Printf("URL: %s\n", req.URL)
fmt.Printf("Headers: %v\n", req.Headers)
fmt.Printf("Body: %s\n", req.Body)
fmt.Printf("Timeout: %d\n", req.Timeout)
}
结构型模式
装饰器模式(Decorator)
动态地给一个对象添加一些额外的职责。
Go 没有类继承,我们用组合和函数式编程来实现:
package main
import (
"fmt"
"net/http"
"time"
)
// 基础处理器
func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello, World!")
}
// 装饰器:日志
func loggingMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next(w, r)
fmt.Printf("%s %s %v\n", r.Method, r.URL.Path, time.Since(start))
}
}
// 装饰器:认证
func authMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
if token == "" {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next(w, r)
}
}
// 装饰器:CORS
func corsMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
next(w, r)
}
}
// 组合多个装饰器
func chain(h http.HandlerFunc, middlewares ...func(http.HandlerFunc) http.HandlerFunc) http.HandlerFunc {
for i := len(middlewares) - 1; i >= 0; i-- {
h = middlewares[i](h)
}
return h
}
func main() {
// 应用装饰器
handler := chain(helloHandler,
loggingMiddleware,
authMiddleware,
corsMiddleware,
)
http.HandleFunc("/", handler)
fmt.Println("服务器启动在 :8080")
http.ListenAndServe(":8080", nil)
}
适配器模式(Adapter)
将一个类的接口转换成客户希望的另外一个接口。
package main
import "fmt"
// Logger 我们期望的接口
type Logger interface {
Info(msg string)
Error(msg string)
}
// ThirdPartyLogger 第三方日志库(有不同的接口)
type ThirdPartyLogger struct{}
func (l *ThirdPartyLogger) LogInfo(msg string) {
fmt.Printf("[INFO] %s\n", msg)
}
func (l *ThirdPartyLogger) LogError(msg string) {
fmt.Printf("[ERROR] %s\n", msg)
}
// LoggerAdapter 适配器
type LoggerAdapter struct {
thirdParty *ThirdPartyLogger
}
func NewLoggerAdapter() *LoggerAdapter {
return &LoggerAdapter{
thirdParty: &ThirdPartyLogger{},
}
}
func (a *LoggerAdapter) Info(msg string) {
a.thirdParty.LogInfo(msg)
}
func (a *LoggerAdapter) Error(msg string) {
a.thirdParty.LogError(msg)
}
// 使用我们定义的接口
func processOrder(logger Logger) {
logger.Info("开始处理订单")
// ... 处理逻辑 ...
logger.Info("订单处理完成")
}
func main() {
// 使用适配器
logger := NewLoggerAdapter()
processOrder(logger)
}
行为型模式
策略模式(Strategy)
定义一系列算法,把它们一个个封装起来,并且使它们可相互替换。
package main
import "fmt"
// SortStrategy 排序策略接口
type SortStrategy interface {
Sort(data []int) []int
}
// BubbleSort 冒泡排序
type BubbleSort struct{}
func (b *BubbleSort) Sort(data []int) []int {
result := make([]int, len(data))
copy(result, data)
n := len(result)
for i := 0; i < n-1; i++ {
for j := 0; j < n-i-1; j++ {
if result[j] > result[j+1] {
result[j], result[j+1] = result[j+1], result[j]
}
}
}
return result
}
// QuickSort 快速排序
type QuickSort struct{}
func (q *QuickSort) Sort(data []int) []int {
result := make([]int, len(data))
copy(result, data)
quickSort(result, 0, len(result)-1)
return result
}
func quickSort(arr []int, low, high int) {
if low < high {
pivot := partition(arr, low, high)
quickSort(arr, low, pivot-1)
quickSort(arr, pivot+1, high)
}
}
func partition(arr []int, low, high int) int {
pivot := arr[high]
i := low - 1
for j := low; j < high; j++ {
if arr[j] < pivot {
i++
arr[i], arr[j] = arr[j], arr[i]
}
}
arr[i+1], arr[high] = arr[high], arr[i+1]
return i + 1
}
// Sorter 使用策略的上下文
type Sorter struct {
strategy SortStrategy
}
func NewSorter(strategy SortStrategy) *Sorter {
return &Sorter{strategy: strategy}
}
func (s *Sorter) SetStrategy(strategy SortStrategy) {
s.strategy = strategy
}
func (s *Sorter) Sort(data []int) []int {
return s.strategy.Sort(data)
}
func main() {
data := []int{64, 34, 25, 12, 22, 11, 90}
// 使用冒泡排序
sorter := NewSorter(&BubbleSort{})
fmt.Println("冒泡排序:", sorter.Sort(data))
// 切换到快速排序
sorter.SetStrategy(&QuickSort{})
fmt.Println("快速排序:", sorter.Sort(data))
}
观察者模式(Observer)
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知。
package main
import (
"fmt"
"sync"
)
// Event 事件
type Event struct {
Type string
Data interface{}
}
// Observer 观察者接口
type Observer interface {
OnEvent(event Event)
}
// EventEmitter 事件发射器(被观察者)
type EventEmitter struct {
observers map[string][]Observer
mu sync.RWMutex
}
func NewEventEmitter() *EventEmitter {
return &EventEmitter{
observers: make(map[string][]Observer),
}
}
func (e *EventEmitter) On(eventType string, observer Observer) {
e.mu.Lock()
defer e.mu.Unlock()
e.observers[eventType] = append(e.observers[eventType], observer)
}
func (e *EventEmitter) Emit(event Event) {
e.mu.RLock()
observers := e.observers[event.Type]
e.mu.RUnlock()
for _, observer := range observers {
observer.OnEvent(event)
}
}
// LoggerObserver 日志观察者
type LoggerObserver struct{}
func (l *LoggerObserver) OnEvent(event Event) {
fmt.Printf("[LOG] 事件: %s, 数据: %v\n", event.Type, event.Data)
}
// MetricsObserver 指标观察者
type MetricsObserver struct {
count int
}
func (m *MetricsObserver) OnEvent(event Event) {
m.count++
fmt.Printf("[METRICS] %s 事件计数: %d\n", event.Type, m.count)
}
// User 用户(被观察对象)
type User struct {
ID int
Name string
Email string
emitter *EventEmitter
}
func NewUser(emitter *EventEmitter) *User {
return &User{emitter: emitter}
}
func (u *User) UpdateEmail(newEmail string) {
oldEmail := u.Email
u.Email = newEmail
u.emitter.Emit(Event{
Type: "user.email_changed",
Data: map[string]interface{}{
"user_id": u.ID,
"old_email": oldEmail,
"new_email": newEmail,
},
})
}
func main() {
emitter := NewEventEmitter()
// 注册观察者
logger := &LoggerObserver{}
metrics := &MetricsObserver{}
emitter.On("user.email_changed", logger)
emitter.On("user.email_changed", metrics)
// 触发事件
user := NewUser(emitter)
user.ID = 1
user.Name = "张三"
user.Email = "old@example.com"
user.UpdateEmail("new@example.com")
}
责任链模式(Chain of Responsibility)
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。
package main
import "fmt"
// Request 请求
type Request struct {
Type string
Amount float64
UserID int
}
// Handler 处理器接口
type Handler interface {
SetNext(handler Handler) Handler
Handle(request *Request) bool
}
// BaseHandler 基础处理器
type BaseHandler struct {
next Handler
}
func (h *BaseHandler) SetNext(handler Handler) Handler {
h.next = handler
return handler
}
func (h *BaseHandler) HandleNext(request *Request) bool {
if h.next != nil {
return h.next.Handle(request)
}
return false
}
// AuthHandler 认证处理器
type AuthHandler struct {
BaseHandler
}
func (h *AuthHandler) Handle(request *Request) bool {
if request.UserID == 0 {
fmt.Println("认证失败:用户未登录")
return false
}
fmt.Println("认证通过")
return h.HandleNext(request)
}
// LimitHandler 限额处理器
type LimitHandler struct {
BaseHandler
limit float64
}
func (h *LimitHandler) Handle(request *Request) bool {
if request.Amount > h.limit {
fmt.Printf("限额检查失败:金额 %.2f 超过限额 %.2f\n", request.Amount, h.limit)
return false
}
fmt.Println("限额检查通过")
return h.HandleNext(request)
}
// RiskHandler 风控处理器
type RiskHandler struct {
BaseHandler
}
func (h *RiskHandler) Handle(request *Request) bool {
// 模拟风控检查
if request.Amount > 10000 {
fmt.Println("风控检查失败:金额过大")
return false
}
fmt.Println("风控检查通过")
return h.HandleNext(request)
}
// ProcessHandler 最终处理器
type ProcessHandler struct {
BaseHandler
}
func (h *ProcessHandler) Handle(request *Request) bool {
fmt.Printf("处理请求:类型=%s, 金额=%.2f, 用户=%d\n",
request.Type, request.Amount, request.UserID)
return true
}
func main() {
// 构建责任链
auth := &AuthHandler{}
limit := &LimitHandler{limit: 50000}
risk := &RiskHandler{}
process := &ProcessHandler{}
auth.SetNext(limit).SetNext(risk).SetNext(process)
// 测试请求
requests := []*Request{
{Type: "transfer", Amount: 1000, UserID: 0}, // 未登录
{Type: "transfer", Amount: 60000, UserID: 1}, // 超限额
{Type: "transfer", Amount: 15000, UserID: 1}, // 风控失败
{Type: "transfer", Amount: 5000, UserID: 1}, // 成功
}
for _, req := range requests {
fmt.Printf("\n--- 处理请求: 金额=%.2f, 用户=%d ---\n", req.Amount, req.UserID)
if auth.Handle(req) {
fmt.Println("✅ 请求处理成功")
} else {
fmt.Println("❌ 请求处理失败")
}
}
}
Go 特有的模式
选项模式(Options Pattern)
这是 Go 社区非常流行的模式,用于处理可选参数:
package main
import (
"fmt"
"time"
)
// Server 服务器配置
type Server struct {
Host string
Port int
ReadTimeout time.Duration
WriteTimeout time.Duration
MaxConns int
}
// Option 选项函数
type Option func(*Server)
// WithHost 设置主机
func WithHost(host string) Option {
return func(s *Server) {
s.Host = host
}
}
// WithPort 设置端口
func WithPort(port int) Option {
return func(s *Server) {
s.Port = port
}
}
// WithTimeout 设置超时
func WithTimeout(read, write time.Duration) Option {
return func(s *Server) {
s.ReadTimeout = read
s.WriteTimeout = write
}
}
// WithMaxConns 设置最大连接数
func WithMaxConns(maxConns int) Option {
return func(s *Server) {
s.MaxConns = maxConns
}
}
// NewServer 创建服务器
func NewServer(options ...Option) *Server {
// 默认值
server := &Server{
Host: "localhost",
Port: 8080,
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
MaxConns: 1000,
}
// 应用选项
for _, option := range options {
option(server)
}
return server
}
func main() {
// 使用默认值
server1 := NewServer()
fmt.Printf("Server 1: %s:%d\n", server1.Host, server1.Port)
// 自定义配置
server2 := NewServer(
WithHost("0.0.0.0"),
WithPort(9090),
WithTimeout(60*time.Second, 60*time.Second),
WithMaxConns(5000),
)
fmt.Printf("Server 2: %s:%d (max=%d)\n",
server2.Host, server2.Port, server2.MaxConns)
}
Worker Pool 模式
package main
import (
"fmt"
"sync"
"time"
)
type Job struct {
ID int
Payload string
}
type Result struct {
JobID int
Output string
}
func worker(id int, jobs <-chan Job, results chan<- Result, wg *sync.WaitGroup) {
defer wg.Done()
for job := range jobs {
// 模拟处理
time.Sleep(100 * time.Millisecond)
result := Result{
JobID: job.ID,
Output: fmt.Sprintf("Worker %d processed: %s", id, job.Payload),
}
results <- result
}
}
func main() {
const (
numWorkers = 5
numJobs = 20
)
jobs := make(chan Job, numJobs)
results := make(chan Result, numJobs)
var wg sync.WaitGroup
// 启动 workers
for i := 1; i <= numWorkers; i++ {
wg.Add(1)
go worker(i, jobs, results, &wg)
}
// 发送任务
for i := 1; i <= numJobs; i++ {
jobs <- Job{ID: i, Payload: fmt.Sprintf("Task %d", i)}
}
close(jobs)
// 等待所有 worker 完成
go func() {
wg.Wait()
close(results)
}()
// 收集结果
for result := range results {
fmt.Println(result.Output)
}
}
小结
今天我们学习了 Go 语言中的设计模式:
创建型模式:
- 单例模式(
sync.Once) - 工厂模式(接口 + 工厂函数)
- 建造者模式(链式调用)
结构型模式:
- 装饰器模式(函数组合)
- 适配器模式(组合)
行为型模式:
- 策略模式(接口 + 上下文)
- 观察者模式(事件发射器)
- 责任链模式(链式处理器)
Go 特有模式:
- 选项模式(函数选项)
- Worker Pool(goroutine 池)
设计模式不是银弹,不要为了用模式而用模式。选择最适合当前场景的方案,写出简洁、可维护的代码。
练习时间
- 实现代理模式:为远程服务调用添加缓存和重试
- 实现命令模式:构建一个支持撤销的操作历史
- 实现状态模式:构建一个订单状态机
- 实现访问者模式:为 AST(抽象语法树)添加不同的操作
我们下篇见!👋
参考资料:
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。