分析model_struct.go下的ModelStruct, StructField 和Relationship
首先, 你需要为实体类定义tag, 比如:
type User struct {
Id int64 `gorm:"primary_key;auto_increment"`
Username string `gorm:"type:varchar(20)"`
Kind string `gorm:"type:varchar(20)"`
Password string `gorm:"type:varchar(32)"`
}
User会被映射为下面的:
PrimaryFields []*StructField
和StructFields []*StructField
会保存那些映射的属性箭头含义为“映射为”
这个文件为Scope定义了两个函数,GetModelStruct和GetStructFields。
var modelStructsMap sync.Map
的作用是ModelStruct的缓存概括而言,该函数会
hashKey
从modelStructsMap查找缓存,找到存放的ModelStruct。该key与scope.Value
的类型有关。如果查到缓存就返回。scope.Value
去寻找对应的结构体,解析tag并返回ModelStruct。 scope.Value
是什么呢?就是db.Model(&user)
或者db.Find(&user)
里的那个userscope.Value
得到其对应的实体struct类型reflectType
. 比如db.Model(&user)
在此会得到User类型modelStructsMap
modelStructsMap
parseTagSetting
解析tag中"sql"或"gorm"开头的部分,并加载为map形式gorm:"-"
,下同)字段,则field.IsIgnored = true
,跳至4. 否则要分析这个属性field.HasDefaultValue = true
indirectType
,当fieldStruct.Type
为指针时,indirectType
则为最终指向的类型 indirectType
为sql.Scanner
、*time.Time
则做出对应处理indirectType
有EMBEDDED字段或为匿名struct,则调用for _, subField := range scope.New(fieldValue).GetModelStruct().StructFields
递归分析嵌套结构体,并遍历其属性(一般gorm.Model会遍历至此): // Even it is ignored, also possible to decode db value into the field if value, ok := field.TagSettingsGet("COLUMN"); ok { field.DBName = value } else { field.DBName = ToColumnName(fieldStruct.Name) }
modelStructsMap.Store(hashKey, &modelStruct)
存入缓存核心是解析结构体的函数GetModelStruct,它会递归调用,并把tag中的信息解析到ModelStruct, StructField和Relationship中。