第38章:插件系统与高级扩展
本章目标
学完本章后,你将能够:
- 理解 GORM 的插件架构
- 配置 DBResolver 实现读写分离
- 了解分库分表插件(Sharding)
- 开发自定义 Plugin
- 了解 Callback 系统
前置知识
- 需要先学习:第04章(配置)、第25-28章(关联+钩子)
38.1 GORM 插件架构
GORM 通过插件接口实现可扩展性:
go
type Plugin interface {
Name() string
Initialize(*gorm.DB) error
}
// 注册插件
db.Use(plugin)内置/社区插件
| 插件 | 功能 |
|---|---|
| DBResolver | 读写分离、多数据源 |
| Sharding | 分库分表 |
| OptimisticLock | 乐观锁 |
| Prometheus | 监控指标 |
| Hints | 索引提示 |
38.2 DBResolver:读写分离
go
import "gorm.io/plugin/dbresolver"
db, _ := gorm.Open(mysql.Open(masterDSN), &gorm.Config{})
db.Use(dbresolver.Register(dbresolver.Config{
Sources: []gorm.Dialector{mysql.Open("master_dsn")}, // 主库(写入)
Replicas: []gorm.Dialector{
mysql.Open("slave1_dsn"), // 从库1(读取)
mysql.Open("slave2_dsn"), // 从库2(读取)
},
Policy: dbresolver.RandomPolicy{}, // 随机选择从库
}))
// 写操作 → 自动使用主库
db.Create(&user)
// 读操作 → 自动使用从库
db.Find(&users)
// 强制使用主库读
db.Clauses(dbresolver.Write).Find(&users)38.3 自定义 Plugin
go
// 自动填充创建人和更新人的插件
type AuditPlugin struct{}
func (p *AuditPlugin) Name() string {
return "audit_plugin"
}
func (p *AuditPlugin) Initialize(db *gorm.DB) error {
// 注册 BeforeCreate 回调
db.Callback().Create().Before("gorm:create").Register("audit:before_create", func(db *gorm.DB) {
if db.Statement.Schema != nil {
if field, ok := db.Statement.Schema.FieldsByName["CreatedBy"]; ok {
field.Set(db.Statement.Context, db.Statement.ReflectValue, "system")
}
}
})
return nil
}
// 使用
db.Use(&AuditPlugin{})
// 之后所有 Create 操作自动填充 CreatedBy38.4 Callback 系统简介
GORM 内部所有操作都是通过 Callback 实现的。你可以注册自己的 Callback 来拦截和修改 SQL 执行流程:
go
// 注册一个 Callback
db.Callback().Create().Before("gorm:create").Register("my_callback", func(db *gorm.DB) {
// 在 Create 之前执行
log.Println("即将执行 INSERT")
})
// Callback 类型
db.Callback().Create() // 创建
db.Callback().Update() // 更新
db.Callback().Delete() // 删除
db.Callback().Query() // 查询
db.Callback().Row() // Row
db.Callback().Raw() // Raw38.5 常用社区插件
bash
# DBResolver(读写分离)
go get gorm.io/plugin/dbresolver
# OptimisticLock(乐观锁)
go get gorm.io/plugin/optimisticlock
# Prometheus(监控)
go get gorm.io/plugin/prometheus
# Sharding(分表)
go get gorm.io/sharding本章小结
- GORM 通过 Plugin 接口实现扩展性
- DBResolver 实现读写分离(主库写、从库读)
- 自定义 Plugin 可以拦截操作流程
- Callback 是 GORM 内部的操作钩子
练习题
- 配置 DBResolver 实现读写分离(至少需要两个 MySQL 实例,可用 Docker)。
- 写一个自定义 Plugin,在每次 Create 前打印日志。
- 注册一个 AfterFind Callback,在查询结果返回前做数据脱敏。
- (思考题)读写分离的延迟问题怎么处理?即主库写入后,从库还没同步,用户立即读到旧数据?