写 Go 写到最后,你会发现:
真正的高手,不是多会写,而是多会“抽象”。
🧬 一、泛型(Generics):让代码重用更优雅
Go 在 1.18 版本引入了泛型,用 []T、any、constraints 表示“类型参数”。
🌰 基础例子
func PrintSlice[T any](s []T) {
for _, v := range s {
fmt.Println(v)
}
}
以前你得写 PrintInts、PrintStrings,现在一行解决。
🌟 常见泛型场景
- 集合操作(如 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 命令生命周期
- 流水线/插件系统
非常常见。
🧠 四、用泛型 + 设计模式 + 钩子,打造可扩展架构
实际项目中,你可以这样组合:
✅ 用泛型写通用的 数据层
✅ 用接口 + 策略模式写 业务模块
✅ 用钩子 + 装饰器模式做 扩展和中间件
例如:
- 一个支持多支付渠道、可热插拔的订单系统
- 一个具备插件机制的微服务框架
这些模式不是生搬硬套,而是根据场景组合。
📈 五、性能和维护的平衡
高阶技巧用得好是“架构优化”,
用不好是“过度设计”。
技术高手的标志:
在可扩展性和复杂度之间找到刚刚好的平衡。
✅ 总结
| 技巧 | 用途 |
|---|---|
| 泛型 | 减少重复代码,提高代码复用 |
| 设计模式 | 解耦模块,提高灵活性 |
| 钩子函数 | 注入扩展,提升可插拔性 |