回调链机制
GORM 通过回调链实现 CRUD 操作的可扩展性,本文解析其执行机制与注册方式。
回调链结构
回调处理器
Go
type processor struct {
db *DB
before string
after string
remove bool
replace bool
match func(*DB) bool
compile func() func(db *DB)
fn func(db *DB)
name string
}
type Callback struct {
logger logger.Interface
processors []*processor
clauses []string // ["create", "query", "update", "delete", "row", "raw"]
}
预定义回调链
GORM 内置 5 条回调链:
| 回调链 | 触发场景 | 默认回调函数 |
|---|---|---|
| Create | db.Create() | Create、Associate、Commit |
| Query | db.Find() | Query、Preload、AfterFind |
| Update | db.Update() | Update、Associate、Commit |
| Delete | db.Delete() | Delete、Associate、Commit |
| Raw | db.Raw() | Raw |
回调执行流程
Create 回调链示例
Go
// GORM 内部注册
callback.Create().Register("gorm:begin_transaction", beginTransaction)
callback.Create().Register("gorm:before_create", beforeCreate)
callback.Create().Register("gorm:save_before_associations", saveBeforeAssociations)
callback.Create().Register("gorm:create", create)
callback.Create().Register("gorm:save_after_associations", saveAfterAssociations)
callback.Create().Register("gorm:after_create", afterCreate)
callback.Create().Register("gorm:commit_or_rollback_transaction", commitOrRollbackTransaction)
执行顺序:
Go
begin_transaction
→ before_create (调用 BeforeSave/BeforeCreate 钩子)
→ save_before_associations
→ create (执行 INSERT)
→ save_after_associations
→ after_create (调用 AfterCreate 钩子)
→ commit_or_rollback_transaction
查询回调链
Go
callback.Query().Register("gorm:query", Query)
callback.Query().Register("gorm:preload", Preload)
callback.Query().Register("gorm:after_query", AfterQuery)
gorm:query:执行 SELECT 并扫描结果gorm:preload:处理Preload()关联加载gorm:after_query:触发AfterFind钩子
自定义回调
注册回调
Go
db.Callback().Create().Register("plugin:audit_log", func(tx *gorm.DB) {
if tx.Error != nil {
return
}
log.Printf("created record: %v", tx.Statement.Dest)
})
回调排序控制
Go
// 在 gorm:create 之前执行
db.Callback().Create().Before("gorm:create").Register("plugin:validate", validate)
// 在 gorm:create 之后执行
db.Callback().Create().After("gorm:create").Register("plugin:notify", notify)
// 替换默认回调
db.Callback().Create().Replace("gorm:create", customCreate)
移除回调
text
db.Callback().Create().Remove("gorm:after_create")
注意事项
回调函数中若发生错误,必须设置
tx.Error,后续回调将跳过。
Replace会覆盖默认回调,谨慎使用,可能导致内置功能失效。
自定义回调应使用命名空间前缀(如
plugin:)避免与内置回调冲突。
要点总结
- GORM 通过 5 条回调链管理 CRUD 生命周期
- 回调通过
Before/After控制执行顺序 - 支持
Register/Replace/Remove动态扩展 - 回调函数中错误处理通过设置
tx.Error实现短路 - 自定义回调应使用命名空间前缀避免冲突
存放路径:D:\git2\jwdev\articles\GORM\专家\源码分析与底层原理\回调链机制.md
📝 发现内容有误?点击此处直接编辑