为了达到这个目的,还需要修改我们的 TableMeta ,在字段里面增加一个 index 字段。暂时不考虑组合情况,我们可以把它定义成:
// ColumnMeta represents model's field, or column
type ColumnMeta struct {
ColumnName string
FieldName string
Typ reflect.Type
IsPrimaryKey bool
IsAutoIncrement bool
// Offset 是字段偏移量。需要注意的是,这里的字段偏移量是相对于整个结构体的偏移量
// 例如在组合的情况下,
// type A struct {
// name string
// B
// }
// type B struct {
// age int
// }
// age 的偏移量是相对于 A 的起始地址的偏移量
Offset uintptr
// IsHolderType 用于表达是否是 Holder 的类型
// 所谓的 Holder,就是指同时实现了 sql.Scanner 和 driver.Valuer 两个接口的类型
IsHolderType bool
Index int
}
仅限中文
使用场景
在 ORM 的底层实现里面,解析结构体的值有两种实现,一种是 unsafe,一种是 reflect。显然 unsafe 大多数时候性能会很好,尤其是在组合的情况下。
但是目前的 reflect 的实现也没有达到最佳状态,例如:
都使用了
FieldByName
,但是我们有更好的选择Field
。我对
Field
和FieldByName
两个做了性能测试,效果如下:在我电脑上执行测试
go test -bench=BenchmarkFieldIndexOrName -benchmem -benchtime=10000x
,得到的结果是:可以看到,by index 远比 by name 快。
所以为了进一步提高性能,我希望能够将这两个地方的
FieldByName
都替换为Field
。为了达到这个目的,还需要修改我们的
TableMeta
,在字段里面增加一个 index 字段。暂时不考虑组合情况,我们可以把它定义成:那么在解析 ColumnMeta 的时候,同时要把这个 Index 设置好。
要求:
Index
, ColumnMeta 在internal/model 包中reflectValue
实现,将FieldByName
替换为Field