10、🎩 Go 高阶编程技巧:泛型、设计模式与“钩子函数”

179 阅读2分钟

写 Go 写到最后,你会发现:
真正的高手,不是多会写,而是多会“抽象”。


🧬 一、泛型(Generics):让代码重用更优雅

Go 在 1.18 版本引入了泛型,用 []Tanyconstraints 表示“类型参数”。

🌰 基础例子

func PrintSlice[T any](s []T) {
    for _, v := range s {
        fmt.Println(v)
    }
}

以前你得写 PrintIntsPrintStrings,现在一行解决。

🌟 常见泛型场景

  • 集合操作(如 map、reduce、filter)
  • 栈、队列等数据结构
  • 通用工具库(减少重复代码)

🏗️ 二、设计模式:在 Go 中如何用得恰到好处?

✅ 策略模式(Strategy)

定义一组算法,把它们封装起来,并让它们可以互换。

type PaymentStrategy interface {
    Pay(amount float64)
}

type WechatPay struct{}
func (w WechatPay) Pay(amount float64) {
    fmt.Println("用微信支付", amount)
}

type Alipay struct{}
func (a Alipay) Pay(amount float64) {
    fmt.Println("用支付宝支付", amount)
}

func Checkout(p PaymentStrategy, amount float64) {
    p.Pay(amount)
}

✅ 装饰器模式(Decorator)

动态地为对象添加新功能。

type Notifier interface {
    Notify(msg string)
}

type BaseNotifier struct{}
func (b BaseNotifier) Notify(msg string) {
    fmt.Println("发送消息:", msg)
}

type SMSDecorator struct {
    Notifier
}
func (s SMSDecorator) Notify(msg string) {
    s.Notifier.Notify(msg)
    fmt.Println("额外发送短信:", msg)
}

🪝 三、钩子函数(Hook):解耦业务的秘密武器

钩子就是 预留函数接口,允许外部注入行为。

🌰 示例

type Processor struct {
    Before func()
    After  func()
}

func (p Processor) Run() {
    if p.Before != nil {
        p.Before()
    }
    fmt.Println("处理中...")
    if p.After != nil {
        p.After()
    }
}

调用方可以自由扩展:

p := Processor{
    Before: func() { fmt.Println("前置处理") },
    After: func() { fmt.Println("后置处理") },
}
p.Run()

这种模式在:

  • HTTP 框架中间件
  • CLI 命令生命周期
  • 流水线/插件系统
    非常常见。

🧠 四、用泛型 + 设计模式 + 钩子,打造可扩展架构

实际项目中,你可以这样组合:

✅ 用泛型写通用的 数据层
✅ 用接口 + 策略模式写 业务模块
✅ 用钩子 + 装饰器模式做 扩展和中间件

例如:

  • 一个支持多支付渠道、可热插拔的订单系统
  • 一个具备插件机制的微服务框架

这些模式不是生搬硬套,而是根据场景组合。


📈 五、性能和维护的平衡

高阶技巧用得好是“架构优化”,
用不好是“过度设计”。

技术高手的标志:
在可扩展性和复杂度之间找到刚刚好的平衡。


✅ 总结

技巧用途
泛型减少重复代码,提高代码复用
设计模式解耦模块,提高灵活性
钩子函数注入扩展,提升可插拔性

🎉 系列收官