Go语言设计原则与设计模式
设计原则
设计原则是软件设计的基础,也是Code Review的重要标准。
- 单一职责原则: 一个结构体只做一件事
- 开闭原则: 用接口支持扩展,无需修改现有代码
- 里氏替换原则: 接口实现要保持行为一致
- 接口隔离原则: 接口要小而专一
- 依赖倒置原则: 依赖接口而非具体实现
1. 单一职责原则 (Single Responsibility Principle, SRP)
定义: 一个类应该只有一个引起它变化的原因
要点:
- 每个结构体只负责一个功能
- 接口设计要小而专一
- 函数职责单一,避免过长函数
示例:
// 违反SRP - 用户管理类承担了太多职责
type UserManager struct{}
func (u *UserManager) CreateUser() {}
func (u *UserManager) SendEmail() {}
func (u *UserManager) GenerateReport() {}// 符合SRP - 职责分离
type UserService struct{} // 用户业务逻辑
type EmailService struct{} // 邮件服务
type ReportService struct{} // 报表服务
2. 开闭原则 (Open-Closed Principle, OCP)
定义: 对扩展开放,对修改关闭
要点:
- 使用接口实现抽象
- 通过组合而非继承扩展功能(继承会把子类和父类紧耦合(尤其在需要修改父类时会影响所有子类)。组合(将职责拆成小模块并互相持有)更符合开闭原则:把不同功能“组装”在一起,而不是改写已有类)
- 利用策略模式、装饰器模式等
示例
// ❌ 错误示例
type PaymentProcessor struct{}func (p *PaymentProcessor) Process(paymentType string) error {switch paymentType {case "credit":// 信用卡逻辑case "paypal":// PayPal逻辑// 新增支付方式需要修改这里}return nil
}// ✅ 正确示例
// 定义接口
type PaymentMethod interface {Process() error
}// 支付处理器 - 无需修改
type PaymentProcessor struct {method PaymentMethod
}func (p *PaymentProcessor) Process() error {return p.method.Process()
}// 具体实现 - 扩展新功能
type CreditCard struct{}
func (c *CreditCard) Process() error { return nil }type PayPal struct{}
func (p *PayPal) Process() error { return nil }
策略模式(Strategy)
把一组算法/策略封装在若干实现里,通过接口动态选择。
type PaymentMethod interface { Process(amount int) error }// 可以通过配置或工厂选择不同策略
func CreatePayment(methodName string) (PaymentMethod, error) {switch methodName {case "credit":return &CreditCard{}, nilcase "paypal":return &PayPal{}, nildefault:return nil, fmt.Errorf("unknown")}
}
更优秀的做法:用注册表(registry)避免修改 CreatePayment
:
var paymentRegistry = map[string]func() PaymentMethod{}func RegisterPayment(name string, ctor func() PaymentMethod) {paymentRegistry[name] = ctor
}func CreatePayment(name string) (PaymentMethod, error) {if ctor, ok := paymentRegistry[name]; ok {return ctor(), nil}return nil, fmt.Errorf("unknown payment: %s", name)
}// 在不同包的 init() 中注册:
// func init() { RegisterPayment("paypal", func(){return &PayPal{}}) }
注册表方法实现了“无需修改 central factory;只需新增实现并注册即可扩展”,符合 OCP。
装饰器模式(Decorator)
在不改变原始实现的前提下,动态地给对象增加功能(例如:日志、重试、限流、指标)。
type LoggingDecorator struct {next PaymentMethod
}func (d *LoggingDecorator) Process(amount int) error {log.Printf("start process %d", amount)err := d.next.Process(amount)if err != nil {log.Printf("error: %v", err)}log.Printf("done")return err
}// 链式组合
base := &CreditCard{}
withRetry := &RetryDecorator{next: base}
withLogging := &LoggingDecorator{next: withRetry}
proc := NewPaymentProcessor(withLogging)
装饰器可以任意组合,扩展行为无需修改 CreditCard
/PayPal
的源码。
3. 里氏替换原则 (Liskov Substitution Principle, LSP)
定义: 子类型必须能够替换掉它们的父类型
要点:
- 接口实现要保持行为一致性
- 避免在实现中抛出意外错误
- 保持接口契约的完整性
示例
// ❌ 错误示例
type Rectangle struct {Width, Height int
}func (r *Rectangle) SetWidth(w int) { r.Width = w }
func (r *Rectangle) SetHeight(h int) { r.Height = h }type Square struct {Rectangle
}func (s *Square) SetWidth(w int) {s.Width = ws.Height = w // 破坏了矩形的行为
}// ✅ 正确示例
type Shape interface {Area() int
}type Rectangle struct {Width, Height int
}func (r *Rectangle) Area() int {return r.Width * r.Height
}type Square struct {Side int
}func (s *Square) Area() int {return s.Side * s.Side
}// 可以安全替换
func CalculateArea(shape Shape) int {return shape.Area()
}
4. 接口隔离原则 (Interface Segregation Principle, ISP)
定义: 不应该依赖不需要的方法
要点:
- 设计小而专一的接口
- 避免胖接口(fat interface)
- 按需组合多个小接口
示例
// ❌ 错误示例
// 胖接口
type Worker interface {Work() errorEat() errorSleep() error
}type Robot struct{}func (r *Robot) Work() error { return nil }
func (r *Robot) Eat() error { panic("robots don't eat") }
func (r *Robot) Sleep() error { panic("robots don't sleep") }//✅ 正确示例
// 小接口
type Worker interface {Work() error
}type Eater interface {Eat() error
}type Sleeper interface {Sleep() error
}// 按需实现
type Robot struct{}
func (r *Robot) Work() error { return nil }type Human struct{}
func (h *Human) Work() error { return nil }
func (h *Human) Eat() error { return nil }
func (h *Human) Sleep() error { return nil }
5. 依赖倒置原则 (Dependency Inversion Principle, DIP)
定义: 高层模块不应该依赖低层模块,两者都应该依赖抽象(接口)
要点:
- 依赖接口而非具体实现
- 使用依赖注入
- 通过工厂模式创建依赖
示例
// ❌ 错误示例
type MySQLDB struct{}
func (db *MySQLDB) Save() error { return nil }// 直接依赖具体实现
type UserService struct {db *MySQLDB
}func (s *UserService) CreateUser() error {return s.db.Save()
}// ✅ 正确示例
// 定义抽象
type Database interface {Save() error
}// 依赖抽象
type UserService struct {db Database
}func NewUserService(db Database) *UserService {return &UserService{db: db}
}func (s *UserService) CreateUser() error {return s.db.Save()
}// 具体实现
type MySQLDB struct{}
func (db *MySQLDB) Save() error { return nil }type PostgresDB struct{}
func (db *PostgresDB) Save() error { return nil }
设计模式
设计模式是解决特定问题的可复用解决方案,分为三大类:
模式分类与应用场景
类型 | 核心目的 | 主要解决问题 |
---|---|---|
创建型 | 对象创建 | 如何灵活创建对象 |
结构型 | 对象组合 | 如何组合对象形成更大结构 |
行为型 | 对象协作 | 如何在对象间分配职责 |
创建型模式
1. 单例模式 (Singleton)
定义:一个类只允许创建一个对象(或者叫实例),那这个类就是一个单例类,这种设计模式就叫作单例设计模式,简称单例模式
应用场景: 配置管理、数据库连接池、日志记录器
Go实现特点:
- 饿汉式:程序启动时初始化
- 懒汉式:首次使用时初始化(sync.Once保证线程安全)
实现方式:
饿汉式
// ConfigSingleton 饿汉式单例,持有配置信息
type ConfigSingleton struct {appName string // 应用名称appVersion string // 应用版本
}// instance 全局唯一单例实例
var instance *ConfigSingleton// Init 在程序启动时初始化实例
func Init() {fmt.Println("init ConfigSingleton")instance = &ConfigSingleton{appName: "MyApp",appVersion: "1.0.0",}
}// GetInstance 获取全局唯一实例(饿汉式单例)
func GetInstance() *ConfigSingleton {return instance
}// NewInstance 创建新的对象(非单例,用于测试)
func NewInstance() *ConfigSingleton {return &ConfigSingleton{appName: "MyApp",appVersion: "1.0.0",}
}
懒汉式
var (lazySingleton *ConfigSingletononce = &sync.Once{}
)// GetLazyInstance 懒汉式
func GetLazyInstance() *ConfigSingleton {// once 内的方法只会执行一次,所以不需要再次判断once.Do(func() {lazySingleton = &ConfigSingleton{appName: "MyApp",appVersion: "1.0.0",}})return lazySingleton
}
2. 工厂模式 (Factory)
适用场景:对象创建比较复杂,或者需要根据条件选择不同实现。
1. 简单工厂
一个工厂方法搞定所有对象的创建:
// 产品接口
type Parser interface{ Parse(data string) }// 具体产品
type JsonParser struct{}
func (JsonParser) Parse(data string) { fmt.Println("json解析", data) }type YamlParser struct{}
func (YamlParser) Parse(data string) { fmt.Println("yaml解析", data) }// 简单工厂
func NewParser(t string) Parser {switch t {case "json":return JsonParser{}case "yaml":return YamlParser{}}return nil
}func main() {p := NewParser("json")p.Parse(`{"a":1}`)
}
缺点:每加一个产品,就要改 NewParser
。
2. 工厂方法
把“创建逻辑”交给每个工厂类,各管各的:
// 产品接口
type Parser interface{ Parse(data string) }// 工厂接口
type Factory interface{ Create() Parser }// json实现
type JsonParser struct{}
func (JsonParser) Parse(data string) { fmt.Println("json解析", data) }
type JsonFactory struct{}
func (JsonFactory) Create() Parser { return JsonParser{} }// yaml实现
type YamlParser struct{}
func (YamlParser) Parse(data string) { fmt.Println("yaml解析", data) }
type YamlFactory struct{}
func (YamlFactory) Create() Parser { return YamlParser{} }func main() {var f Factory = JsonFactory{}p := f.Create()p.Parse(`{"a":1}`)
}
👉 好处:新增产品不用改旧代码,只要加工厂。
3. 抽象工厂
一次性生产一整组“相关产品”:
// 两类产品接口
type Button interface{ Click() }
type TextBox interface{ Show() }// 抽象工厂
type UIFactory interface {CreateButton() ButtonCreateTextBox() TextBox
}// win系列
type WinButton struct{}
func (WinButton) Click() { fmt.Println("Win按钮") }
type WinTextBox struct{}
func (WinTextBox) Show() { fmt.Println("Win文本框") }
type WinFactory struct{}
func (WinFactory) CreateButton() Button { return WinButton{} }
func (WinFactory) CreateTextBox() TextBox { return WinTextBox{} }func main() {var f UIFactory = WinFactory{}f.CreateButton().Click()f.CreateTextBox().Show()
}
一次性创建“产品族”(比如 Win 系列组件 / Mac 系列组件)。
4. DI 容器(依赖注入容器)
核心思想:不用自己 new
,交给容器管理,随用随取。
// 定义一个容器
type Container struct {beans map[string]func() any // 保存构造函数
}func NewContainer() *Container {return &Container{beans: make(map[string]func() any)}
}// 注册:名字 + 构造函数
func (c *Container) Register(name string, creator func() any) {c.beans[name] = creator
}// 获取:调用构造函数生成对象
func (c *Container) Get(name string) any {if creator, ok := c.beans[name]; ok {return creator()}return nil
}// ================== 示例 ==================
type UserRepo struct{}
func (UserRepo) Find() { fmt.Println("查用户") }type UserService struct {Repo UserRepo
}
func (u UserService) Do() { u.Repo.Find() }func main() {c := NewContainer()// 注册依赖c.Register("repo", func() any { return UserRepo{} })c.Register("service", func() any {return UserService{Repo: c.Get("repo").(UserRepo)}})// 获取对象(自动注入依赖)s := c.Get("service").(UserService)s.Do()
}
- 你不需要自己去写
new UserService(UserRepo{})
- 只要在容器里注册好,拿的时候容器会帮你注入依赖
3. 建造者模式 (Builder)
应用场景: 复杂对象的分步构建、可选参数很多的对象创建
适用场景:
- 构建对象步骤多、参数多
- 有些参数可选,不想写一大堆构造函数
// Computer 产品:电脑
type Computer struct {CPU stringMemory intDisk intGPU string
}// ComputerBuilder Builder
type ComputerBuilder struct {cpu stringmemory intdisk intgpu string
}// NewComputerBuilder 链式调用设置参数
func NewComputerBuilder() *ComputerBuilder { return &ComputerBuilder{} }
func (b *ComputerBuilder) SetCPU(cpu string) *ComputerBuilder {b.cpu = cpureturn b
}
func (b *ComputerBuilder) SetMemory(m int) *ComputerBuilder {b.memory = mreturn b
}
func (b *ComputerBuilder) SetDisk(d int) *ComputerBuilder {b.disk = dreturn b
}
func (b *ComputerBuilder) SetGPU(g string) *ComputerBuilder {b.gpu = greturn b
}// Build 构建最终对象
func (b *ComputerBuilder) Build() Computer {fmt.Println("开始构建电脑...")if b.cpu == "" {b.cpu = "Intel i7"}if b.memory == 0 {b.memory = 16}if b.disk == 0 {b.disk = 512}if b.gpu == "" {b.gpu = "RTX 3080"}return Computer{CPU: b.cpu, Memory: b.memory, Disk: b.disk, GPU: b.gpu}
}func main() {// 灵活选择参数,链式调用pc := NewComputerBuilder().SetCPU("Intel i9").SetMemory(32).Build()fmt.Printf("电脑配置: %+v\n", pc)
}
- 链式调用:
builder.SetCPU().SetDisk().Build()
- 可选参数:只设置关心的字段,不用写一堆构造函数
- 复杂对象组装:一步步构建,最后 `Build()
结构型模式
1. 代理模式 (Proxy)
代理就像“中间人”,在访问真正对象之前,先经过它。
应用场景: 访问控制、缓存、延迟加载、日志记录
实现方式:
- 静态代理:编译时确定代理关系
- 动态代理:使用go generate模拟运行时代理
package mainimport "fmt"// 接口
type Service interface {DoSomething()
}// 真实对象
type RealService struct{}func (r *RealService) DoSomething() {fmt.Println("执行真正的业务逻辑")
}// 代理对象
type Proxy struct {real *RealService
}func (p *Proxy) DoSomething() {fmt.Println("代理:先检查权限")p.real.DoSomething()fmt.Println("代理:记录日志")
}func main() {service := &Proxy{real: &RealService{}}service.DoSomething()
}
2. 桥接模式 (Bridge)
桥接模式就像“插头和插座”分开设计:
- 插头(抽象)只负责定义接口;
- 插座(实现)可以随便换。
这样两边都能独立扩展,互不影响。
应用场景:
比如“消息通知”有多种消息类型(普通、加急)和多种发送方式(短信、邮件、微信)。
如果用继承,会爆炸式增加子类;
用桥接,只要组合就行。
package mainimport "fmt"// Sender 实现层接口
type Sender interface {Send(msg string)
}// EmailSender 不同实现
type EmailSender struct{}
func (e *EmailSender) Send(msg string) { fmt.Println("邮件发送:", msg) }type SmsSender struct{}
func (s *SmsSender) Send(msg string) { fmt.Println("短信发送:", msg) }// Message 抽象层
type Message struct {sender Sender
}func (m *Message) SetSender(s Sender) { m.sender = s }type NormalMessage struct{ Message }
func (m *NormalMessage) Send(msg string) { m.sender.Send("[普通]" + msg) }type UrgentMessage struct{ Message }
func (m *UrgentMessage) Send(msg string) { m.sender.Send("[加急]" + msg) }func main() {normal := &NormalMessage{}normal.SetSender(&EmailSender{})normal.Send("开会通知")urgent := &UrgentMessage{}urgent.SetSender(&SmsSender{})urgent.Send("服务器宕机!")
}
- 抽象和实现分开(消息 vs 发送方式)
- 通过组合来桥接,避免继承爆炸
3. 装饰器模式 (Decorator)
装饰器就像“给咖啡加料”☕:
- 咖啡本身能喝;
- 你可以加牛奶、加糖、加奶泡;
- 每次加的东西都“包一层”,功能越来越多。
应用场景:
- 日志增强
- 权限校验
- Web 中间件
package mainimport "fmt"// 接口
type Component interface {Operation()
}// 具体实现
type ConcreteComponent struct{}
func (c *ConcreteComponent) Operation() { fmt.Println("基础功能") }// 装饰器基类
type Decorator struct {component Component
}
func (d *Decorator) Operation() {if d.component != nil {d.component.Operation()}
}// 具体装饰器1:加日志
type LogDecorator struct{ Decorator }
func (d *LogDecorator) Operation() {fmt.Println("日志: 调用前")d.Decorator.Operation()fmt.Println("日志: 调用后")
}// 具体装饰器2:加权限
type AuthDecorator struct{ Decorator }
func (d *AuthDecorator) Operation() {fmt.Println("权限检查")d.Decorator.Operation()
}func main() {base := &ConcreteComponent{}withLog := &LogDecorator{Decorator{base}}withAuth := &AuthDecorator{Decorator{withLog}}withAuth.Operation()
}
和代理模式很像,但它重点是增强功能(可叠加),
而代理模式更强调控制访问。
4. 适配器模式 (Adapter)
适配器就像“插头转换器”。
- 你买了个电器(美式插头),
- 但家里是国标插座,
- 就需要一个“适配器”来转接。
应用场景:
- 新旧系统对接
- 使用第三方库时接口不一致
- 统一不同实现的调用方式
package mainimport "fmt"// 目标接口 (新系统需要的)
type Target interface {Request()
}// 被适配者 (老系统/第三方库)
type Adaptee struct{}
func (a *Adaptee) SpecificRequest() {fmt.Println("老接口的调用")
}// 适配器
type Adapter struct {adaptee *Adaptee
}
func (ad *Adapter) Request() {fmt.Print("适配器转换 -> ")ad.adaptee.SpecificRequest()
}func main() {adaptee := &Adaptee{}adapter := &Adapter{adaptee}adapter.Request()
}
行为型模式
1. 观察者模式 (Observer)
- 一个对象(被观察者)状态变化时,自动通知所有「订阅」它的对象(观察者)。
- 就像公众号发文章 → 所有粉丝都会收到通知。
应用场景: 事件处理、发布订阅、状态变化通知
扩展实现: 基础观察者模式 / EventBus事件总线
基础观察者模式
// 观察者接口
type Observer interface {Update(msg string)
}// 具体观察者
type User struct{ name string }
func (u *User) Update(msg string) {fmt.Printf("%s 收到通知: %s\n", u.name, msg)
}// 被观察者
type WeChat struct{ subs []Observer }
func (w *WeChat) Add(o Observer) { w.subs = append(w.subs, o) }
func (w *WeChat) Notify(msg string) {for _, o := range w.subs { o.Update(msg) }
}func main() {wx := &WeChat{}wx.Add(&User{"小明"})wx.Add(&User{"小红"})wx.Notify("新文章上线啦!")
}
EventBus 事件总线(更灵活)
type EventBus struct{ subs map[string][]func(string) }func NewBus() *EventBus { return &EventBus{subs: map[string][]func(string){}} }
func (b *EventBus) Subscribe(topic string, fn func(string)) {b.subs[topic] = append(b.subs[topic], fn)
}
func (b *EventBus) Publish(topic, msg string) {for _, fn := range b.subs[topic] { fn(msg) }
}func main() {bus := NewBus()bus.Subscribe("news", func(m string) { fmt.Println("小明:", m) })bus.Subscribe("news", func(m string) { fmt.Println("小红:", m) })bus.Publish("news", "今晚有更新!")
}
2. 模板模式 (Template Method)
模板方法适用于算法骨架固定,但某些具体步骤可以变化的场景。通过定义一个算法的框架,将一些步骤延迟到子类中,从而使得子类可以在不改变算法结构的情况下重新定义算法的某些特定步骤。
应用场景: 比如你要做一个制作饮料的流程:做饮料的步骤固定,但不同饮料的具体步骤可能不同(比如:泡茶、加糖、加奶等)。
// Beverage 饮料接口
type Beverage interface {BoilWater()Brew()PourInCup()CustomerWantsCondiments() boolAddCondiments()MakeBeverage()
}// CaffeineBeverage 定义制作饮料的模板
type CaffeineBeverage struct {beverage Beverage
}func (cb *CaffeineBeverage) MakeBeverage() {cb.beverage.BoilWater()cb.beverage.Brew()cb.beverage.PourInCup()if cb.beverage.CustomerWantsCondiments() {cb.beverage.AddCondiments()}
}// Tea 具体的子类:茶
type Tea struct{}func (t *Tea) BoilWater() {fmt.Println("Boiling water for tea.")
}func (t *Tea) Brew() {fmt.Println("Steeping the tea.")
}func (t *Tea) PourInCup() {fmt.Println("Pouring tea into cup.")
}func (t *Tea) CustomerWantsCondiments() bool {var answer stringfmt.Println("Do you want lemon with your tea (y/n)?")_, err := fmt.Scanln(&answer)if err != nil {return false}return answer == "y"
}func (t *Tea) AddCondiments() {fmt.Println("Adding lemon to tea.")
}func (t *Tea) MakeBeverage() {cb := &CaffeineBeverage{beverage: t}cb.MakeBeverage()
}// Coffee 具体的子类:咖啡
type Coffee struct{}func (c *Coffee) BoilWater() {fmt.Println("Boiling water for coffee.")
}func (c *Coffee) Brew() {fmt.Println("Brewing the coffee.")
}func (c *Coffee) PourInCup() {fmt.Println("Pouring coffee into cup.")
}func (c *Coffee) CustomerWantsCondiments() bool {var answer stringfmt.Println("Do you want milk and sugar with your coffee (y/n)?")_, err := fmt.Scanln(&answer)if err != nil {return false}return answer == "y"
}func (c *Coffee) AddCondiments() {fmt.Println("Adding milk and sugar to coffee.")
}func (c *Coffee) MakeBeverage() {cb := &CaffeineBeverage{beverage: c}cb.MakeBeverage()
}func main() {// 测试:制作茶tea := &Tea{}tea.MakeBeverage()// 测试:制作咖啡coffee := &Coffee{}coffee.MakeBeverage()
}
3. 策略模式 (Strategy)
定义一系列的算法(策略),并将每一个算法封装起来,使它们可以互相替换。策略模式使得算法的变化独立于使用算法的客户。
应用场景:
- 算法族: 你有多种算法或策略可选,且这些算法可以在运行时切换。
- 条件分支优化: 在代码中有很多条件判断,策略模式能有效地替代这些复杂的条件判断。
- 支付方式选择: 比如支付系统,用户可以选择不同的支付方式(支付宝、微信、信用卡等),策略模式可以用来封装这些支付方式的实现。
// PaymentStrategy 支付策略接口
type PaymentStrategy interface {Pay(amount float64)
}// Alipay 支付宝支付
type Alipay struct{}func (a *Alipay) Pay(amount float64) {fmt.Printf("Paying %.2f using Alipay.\n", amount)
}// WeChatPay 微信支付
type WeChatPay struct{}func (w *WeChatPay) Pay(amount float64) {fmt.Printf("Paying %.2f using WeChat Pay.\n", amount)
}// CreditCardPay 信用卡支付
type CreditCardPay struct{}func (c *CreditCardPay) Pay(amount float64) {fmt.Printf("Paying %.2f using Credit Card.\n", amount)
}// PaymentContext 上下文:支付上下文
type PaymentContext struct {Strategy PaymentStrategy
}func (p *PaymentContext) SetStrategy(strategy PaymentStrategy) {p.Strategy = strategy
}func (p *PaymentContext) ExecutePayment(amount float64) {p.Strategy.Pay(amount)
}func main() {// 创建支付上下文context := &PaymentContext{}// 用户选择支付宝支付context.SetStrategy(&Alipay{})context.ExecutePayment(100.0)// 用户选择微信支付context.SetStrategy(&WeChatPay{})context.ExecutePayment(200.0)// 用户选择信用卡支付context.SetStrategy(&CreditCardPay{})context.ExecutePayment(300.0)
}
4. 职责链模式 (Chain of Responsibility)
应用场景: 请求处理链、中间件、审批流程
实际应用: Gin框架的中间件实现
- 多个处理器(Handler)排成一条链,依次处理请求。
- 每个处理器可以选择:处理后交给下一个,或者直接拦截。
- 就像请假审批:组长 → 经理 → 老板。
基础职责链
// Handler接口
type Handler interface {Handle(req int)SetNext(h Handler)
}type Base struct{ next Handler }
func (b *Base) SetNext(h Handler) { b.next = h }
func (b *Base) CallNext(req int) { if b.next != nil { b.next.Handle(req) } }// 具体处理器
type Leader struct{ Base }
func (l *Leader) Handle(req int) {if req <= 1 {fmt.Println("Leader 批准")} else { l.CallNext(req) }
}type Manager struct{ Base }
func (m *Manager) Handle(req int) {if req <= 3 {fmt.Println("Manager 批准")} else { m.CallNext(req) }
}type Boss struct{ Base }
func (b *Boss) Handle(req int) {fmt.Println("Boss 批准")
}func main() {leader, manager, boss := &Leader{}, &Manager{}, &Boss{}leader.SetNext(manager)manager.SetNext(boss)leader.Handle(2) // 输出 Manager 批准
}
类似 Gin 中间件实现
type HandlerFunc func(int, func())func main() {// 定义中间件m1 := func(req int, next func()) {fmt.Println("m1 before")next()fmt.Println("m1 after")}m2 := func(req int, next func()) {fmt.Println("m2 before")next()}// 模拟执行链chain := func(req int, m []HandlerFunc) {var exec func(int, int)exec = func(req, idx int) {if idx < len(m) {m[idx](req, func() { exec(req, idx+1) })}}exec(req, 0)}chain(123, []HandlerFunc{m1, m2})
}
5. 状态模式 (State)
- 状态模式就是把「状态」单独抽成类,不同状态有不同的行为。
- 对象的行为会随着状态切换而改变。
- 就像红绿灯:红灯停,绿灯行,黄灯等。
应用场景: 状态机、工作流、游戏状态
示例:订单状态机
// 状态接口
type State interface {Next(*Order)Show()
}// 具体状态
type Created struct{}
func (s *Created) Next(o *Order) { o.state = &Paid{} }
func (s *Created) Show() { fmt.Println("订单已创建") }type Paid struct{}
func (s *Paid) Next(o *Order) { o.state = &Shipped{} }
func (s *Paid) Show() { fmt.Println("订单已支付") }type Shipped struct{}
func (s *Shipped) Next(o *Order) { o.state = &Done{} }
func (s *Shipped) Show() { fmt.Println("订单已发货") }type Done struct{}
func (s *Done) Next(o *Order) {}
func (s *Done) Show() { fmt.Println("订单完成") }// 上下文
type Order struct{ state State }
func (o *Order) Next() { o.state.Next(o) }
func (o *Order) Show() { o.state.Show() }func main() {order := &Order{state: &Created{}}order.Show() // 订单已创建order.Next()order.Show() // 订单已支付order.Next()order.Show() // 订单已发货order.Next()order.Show() // 订单完成
}
6. 迭代器模式 (Iterator)
- 不暴露集合内部结构,就能顺序访问集合里的元素。
- 就像翻书:只管一页一页往下翻,不需要知道书里怎么装订的。
应用场景: 集合遍历、数据流处理
package mainimport "fmt"// 迭代器接口
type Iterator interface {HasNext() boolNext() any
}// 具体迭代器
type IntIterator struct {data []intidx int
}
func (it *IntIterator) HasNext() bool { return it.idx < len(it.data) }
func (it *IntIterator) Next() any {val := it.data[it.idx]it.idx++return val
}// 集合
type IntCollection struct{ data []int }
func (c *IntCollection) Iterator() Iterator {return &IntIterator{data: c.data}
}func main() {coll := &IntCollection{data: []int{10, 20, 30}}it := coll.Iterator()for it.HasNext() {fmt.Println(it.Next())}
}