GORM 内核架构解析
GORM 内核由多个核心组件协同工作,本文解析其内部架构与数据流转机制。
核心组件
DB 组件
DB 是 GORM 的顶层对象,封装 *sql.DB 连接池与全局配置:
Go
type DB struct {
*Config
Statement *Statement
Error error
RowsAffected *int64
clones []*DB
}
Config:存储 DSN、日志、命名参数等全局配置Statement:当前查询的构建状态clones:会话克隆列表,用于并发安全
Statement 组件
Statement 是 SQL 构建的核心载体,持有查询的所有中间状态:
Go
type Statement struct {
DB *DB
TableExpr *expr
Table string
Dest interface{}
ReflectValue reflect.Value
Clauses map[string]clause.Clause
BuildClauses []string
Distinct bool
Selects []string
Joins []join
Preloads map[string][]interface{}
// ... 更多字段
}
关键职责:
- 收集
Where、Select、Order等子句 - 维护目标结构体的反射值
- 最终委托
clause.Builder生成 SQL
Resolver 机制
Resolver 负责解析数据源的表名、主键、关联关系:
Go
// 表名解析
type Tabler interface {
TableName() string
}
// 主键解析
stmt.Schema.PrimaryFields // 从 Schema 中获取主键字段
- 通过接口
Tabler支持自定义表名 - 通过
Schema缓存结构体的元数据(字段、标签、关联)
数据流分析
查询执行流程
Go
db.Where("age > ?", 18).Find(&users)
执行流程:
db.Where()→ 克隆新*DB,写入Statement.Clauses["WHERE"]Find()→ 触发callback.Query链- 回调链调用
statement.Build("SELECT", "FROM", "WHERE") clause.Builder遍历子句,拼接最终 SQL- 执行
db.ConnPool.QueryContext()获取结果 - 反射扫描结果集到
Dest
会话克隆机制
Go
func (db *DB) Session(config *Session) *DB {
newDB := db.getInstance()
if config.DryRun {
newDB.Config.DryRun = true
}
// ... 应用其他配置
return newDB
}
func (db *DB) getInstance() *DB {
newDB := &DB{}
*newDB = *db
newDB.Statement = &Statement{DB: newDB}
*newDB.Statement = *db.Statement
newDB.Statement.DB = newDB
return newDB
}
- 每次链式调用克隆新实例,保证原
DB不受影响 - 浅拷贝
Config,深拷贝Statement
注意事项
并发场景下,必须使用
Session()或链式调用获取新实例,不可共享同一*DB进行写操作。
Statement内部维护大量状态,复杂查询应适时调用Statement.Clear()避免状态污染。
要点总结
DB是顶层封装,持有连接池与配置Statement是 SQL 构建核心,收集所有查询子句- Resolver 通过接口与 Schema 缓存解析元数据
- 链式调用通过会话克隆实现并发安全
- 数据流:链式调用 → 回调链 → clause.Build → 执行 → 反射扫描
存放路径:D:\git2\jwdev\articles\GORM\专家\源码分析与底层原理\GORM 内核架构解析.md
📝 发现内容有误?点击此处直接编辑