@@ -9,163 +9,164 @@ package gdb
99import (
1010 "fmt"
1111 "reflect"
12+ "strings"
1213 "sync"
13-
14- "github.com/gogf/gf/v2/text/gstr"
1514)
1615
17- // ==================== 字段元数据缓存管理器 ====================
18- // 设计原则:
19- // 1. 仅缓存确定性信息(字段索引、类型判断)
20- // 2. 保留动态查找能力(嵌入字段、大小写不敏感)
21- // 3. 使用 sync.Map 保证高性能并发读取
16+ // Field metadata cache manager
17+ // Design principle:
18+ // 1. Cache deterministic information only (field index, type judgment)
19+ // 2. Retain dynamic lookup capability (embedded fields, case insensitive)
20+ // 3. Use sync.Map to ensure high performance concurrent access
2221
23- // fieldCacheManager 字段缓存管理器
22+ // fieldCacheManager field cache manager
2423type fieldCacheManager struct {
2524 cache sync.Map // map[string]*fieldCache
2625}
2726
28- // newFieldCacheManager 创建字段缓存管理器
27+ // newFieldCacheManager creates field cache manager
2928func newFieldCacheManager () * fieldCacheManager {
3029 return & fieldCacheManager {}
3130}
3231
33- // fieldCacheMgr 全局字段缓存管理器实例
34- var fieldCacheMgr = newFieldCacheManager ()
32+ // fieldCacheInstance global field cache manager instance
33+ var fieldCacheInstance = newFieldCacheManager ()
3534
36- // fieldCache 字段缓存
37- // 存储可以安全缓存的确定性字段信息,避免在循环内重复反射
35+ // fieldCache field cache
36+ // Stores deterministic field information that can be safely cached to avoid repeated reflection in loops
3837type fieldCache struct {
39- // 确定性字段索引(可安全缓存)
40- bindToAttrIndex int // 绑定属性的字段索引(如 UserDetail)
41- relationAttrIndex int // 关系属性的字段索引(如 User,-1表示无)
42- isPointerElem bool // 数组元素是否为指针类型
43- bindToAttrKind reflect.Kind // 绑定属性的类型
38+ // Deterministic field index (can be safely cached)
39+ bindToAttrIndex int // Field index of bound attribute (e.g. UserDetail)
40+ relationAttrIndex int // Field index of relation attribute (e.g. User, -1 means none)
41+ isPointerElem bool // Whether array element is pointer type
42+ bindToAttrKind reflect.Kind // Type of bound attribute
4443
45- // 字段名映射(支持大小写不敏感查找)
44+ // Field name mapping (supports case-insensitive lookup)
4645 fieldNameMap map [string ]string // lowercase -> OriginalName
4746 fieldIndexMap map [string ]int // FieldName -> Index
4847}
4948
50- // getOrBuild 获取或构建缓存(线程安全)
51- func (m * fieldCacheManager ) getOrBuild (
49+ // getOrSet gets or sets cache (thread-safe)
50+ func (m * fieldCacheManager ) getOrSet (
5251 arrayItemType reflect.Type ,
5352 bindToAttrName string ,
5453 relationAttrName string ,
5554) (* fieldCache , error ) {
56- // 构建缓存键
55+ // Build cache key
5756 cacheKey := m .buildCacheKey (arrayItemType , bindToAttrName , relationAttrName )
5857
59- // 快速路径:缓存命中
58+ // Fast path: cache hit
6059 if cached , ok := m .cache .Load (cacheKey ); ok {
6160 return cached .(* fieldCache ), nil
6261 }
6362
64- // 慢速路径:构建缓存
63+ // Slow path: build cache
6564 cache , err := m .buildCache (arrayItemType , bindToAttrName , relationAttrName )
6665 if err != nil {
6766 return nil , err
6867 }
6968
70- // 存储到缓存(如果并发构建,只有一个会被保存)
69+ // Store to cache (if built concurrently, only one will be saved)
7170 actual , _ := m .cache .LoadOrStore (cacheKey , cache )
7271 return actual .(* fieldCache ), nil
7372}
7473
75- // buildCacheKey 构建缓存键
74+ // buildCacheKey builds the cache key
7675func (m * fieldCacheManager ) buildCacheKey (
7776 typ reflect.Type ,
7877 bindToAttrName string ,
7978 relationAttrName string ,
8079) string {
81- // 使用类型的唯一标识 + 字段名组合
82- return fmt .Sprintf ("%s|%s|%s" , typ .String (), bindToAttrName , relationAttrName )
80+ // Estimate capacity: type name + two field names + 2 separators
81+ var builder strings.Builder
82+ typeName := typ .String ()
83+ builder .Grow (len (typeName ) + len (bindToAttrName ) + len (relationAttrName ) + 2 )
84+
85+ builder .WriteString (typeName )
86+ builder .WriteByte ('|' )
87+ builder .WriteString (bindToAttrName )
88+ builder .WriteByte ('|' )
89+ builder .WriteString (relationAttrName )
90+
91+ return builder .String ()
8392}
8493
85- // buildCache 构建字段访问缓存
94+ // buildCache builds field access cache
8695func (m * fieldCacheManager ) buildCache (
8796 arrayItemType reflect.Type ,
8897 bindToAttrName string ,
8998 relationAttrName string ,
9099) (* fieldCache , error ) {
91- cache := & fieldCache {
92- relationAttrIndex : - 1 , // 默认值
93- fieldNameMap : make (map [string ]string ),
94- fieldIndexMap : make (map [string ]int ),
95- }
96-
97- // 获取实际的结构体类型
100+ // Get the actual struct type
98101 structType := arrayItemType
102+ isPointerElem := false
99103 if structType .Kind () == reflect .Pointer {
100104 structType = structType .Elem ()
101- cache . isPointerElem = true
105+ isPointerElem = true
102106 }
103107
104108 if structType .Kind () != reflect .Struct {
105109 return nil , fmt .Errorf ("arrayItemType must be struct or pointer to struct, got: %s" , arrayItemType .Kind ())
106110 }
107111
108- // 遍历所有字段,构建字段映射
109112 numField := structType .NumField ()
113+ cache := & fieldCache {
114+ relationAttrIndex : - 1 ,
115+ isPointerElem : isPointerElem ,
116+ fieldNameMap : make (map [string ]string , numField ), // Pre-allocate capacity
117+ fieldIndexMap : make (map [string ]int , numField ), // Pre-allocate capacity
118+ }
119+
120+ // Iterate all fields, build field mapping
110121 for i := 0 ; i < numField ; i ++ {
111122 field := structType .Field (i )
112123 fieldName := field .Name
113124
114125 cache .fieldIndexMap [fieldName ] = i
115- cache .fieldNameMap [gstr .ToLower (fieldName )] = fieldName
126+ cache .fieldNameMap [strings .ToLower (fieldName )] = fieldName
116127 }
117128
118- // 查找 bindToAttrName 字段索引
129+ // Find bindToAttrName field index
119130 if idx , ok := cache .fieldIndexMap [bindToAttrName ]; ok {
120131 cache .bindToAttrIndex = idx
121132 field := structType .Field (idx )
122133 cache .bindToAttrKind = field .Type .Kind ()
123- } else if originalName , ok := cache .fieldNameMap [gstr .ToLower (bindToAttrName )]; ok {
124- // 大小写不敏感查找
125- cache .bindToAttrIndex = cache .fieldIndexMap [originalName ]
126- field := structType .Field (cache .bindToAttrIndex )
127- cache .bindToAttrKind = field .Type .Kind ()
128134 } else {
129- return nil , fmt .Errorf (`field "%s" not found in type %s` , bindToAttrName , arrayItemType .String ())
135+ // Case-insensitive lookup
136+ lowerBindName := strings .ToLower (bindToAttrName )
137+ if originalName , ok := cache .fieldNameMap [lowerBindName ]; ok {
138+ cache .bindToAttrIndex = cache .fieldIndexMap [originalName ]
139+ field := structType .Field (cache .bindToAttrIndex )
140+ cache .bindToAttrKind = field .Type .Kind ()
141+ } else {
142+ return nil , fmt .Errorf (`field "%s" not found in type %s` , bindToAttrName , arrayItemType .String ())
143+ }
130144 }
131145
132- // 查找 relationAttrName 字段索引(可选)
146+ // Find relationAttrName field index (optional)
133147 if relationAttrName != "" {
134148 if idx , ok := cache .fieldIndexMap [relationAttrName ]; ok {
135149 cache .relationAttrIndex = idx
136- } else if originalName , ok := cache .fieldNameMap [gstr .ToLower (relationAttrName )]; ok {
137- cache .relationAttrIndex = cache .fieldIndexMap [originalName ]
150+ } else {
151+ // Case-insensitive lookup
152+ lowerRelName := strings .ToLower (relationAttrName )
153+ if originalName , ok := cache .fieldNameMap [lowerRelName ]; ok {
154+ cache .relationAttrIndex = cache .fieldIndexMap [originalName ]
155+ }
138156 }
139- // 注意:如果找不到,保持 -1,表示需要使用 arrayElemValue 本身
157+ // Note: if not found, keep -1, indicating that arrayElemValue itself should be used
140158 }
141159
142160 return cache , nil
143161}
144162
145- // clear 清空所有缓存(测试或热更新时使用)
163+ // clear clears all cache (used for testing or hot updates)
146164func (m * fieldCacheManager ) clear () {
147- m .cache .Range (func (key , value any ) bool {
148- m .cache .Delete (key )
149- return true
150- })
151- }
152-
153- // stats 获取缓存统计信息
154- func (m * fieldCacheManager ) stats () (count int ) {
155- m .cache .Range (func (key , value any ) bool {
156- count ++
157- return true
158- })
159- return count
165+ m .cache .Clear ()
160166}
161167
162- // ClearFieldCache 清空字段缓存(供外部调用)
163- // 用于测试或应用热更新场景
168+ // ClearFieldCache clears field cache (for external calls)
169+ // Used for testing or application hot update scenarios
164170func ClearFieldCache () {
165- fieldCacheMgr .clear ()
166- }
167-
168- // GetFieldCacheStats 获取字段缓存统计信息(供监控使用)
169- func GetFieldCacheStats () int {
170- return fieldCacheMgr .stats ()
171+ fieldCacheInstance .clear ()
171172}
0 commit comments