Go中如何通过Gorm的db对象获取模型字段映射的PostgreSQL类型?
Gorm获取模型字段对应数据库类型的方法
问题解答
1. 能否通过*gorm.DB获取字段的数据库类型?
可以,你需要先获取对应模型的解析后Schema对象,即可直接读取每个字段的数据库类型定义。
你拿到的db.Schema为nil是正常的,该字段是Gorm内部存储当前连接数据库元信息的属性,和你的业务模型Schema无关,属于找错了存储位置。
2. ParseField的调用位置和解析结果存储规则
ParseField是在schema.Parse方法内部被调用的:schema.Parse遍历结构体的所有公开字段时,会对每个符合Gorm映射规则的字段调用ParseField解析标签、数据类型、约束等属性。- 解析结果的存储有两个路径:
- 你手动调用
schema.Parse时会直接返回解析完成的*schema.Schema实例,所有字段的解析结果都存在该实例的Fields属性中。 - Gorm自动触发解析(比如调用
AutoMigrate、Model、Find等方法操作模型时)后,会把解析结果存在*gorm.DB的SchemaCache缓存中,同一模型只会解析一次。
- 你手动调用
3. 具体实现代码
方式1:手动解析模型Schema(最稳妥,不会依赖是否触发过自动解析)
import ( "gorm.io/gorm/schema" "sync" ) // 假设db为已初始化的*gorm.DB实例 func getModelFieldTypes(db *gorm.DB) error { // 解析MyModel的Schema,第二个参数是临时缓存,你也可以传db.SchemaCache复用全局缓存 modelSchema, err := schema.Parse(&MyModel{}, &sync.Map{}, db.Config.NamingStrategy) if err != nil { return err } // 遍历字段获取数据库类型 for _, field := range modelSchema.Fields { // 输出示例:FirstField -> numeric,SecondField -> varchar(42) println("字段名:", field.Name, "对应PostgreSQL类型:", field.DataType) } return nil }
方式2:从全局缓存读取(仅当你之前已经操作过该模型时可用)
import "reflect" // 先触发一次自动解析,结果存入SchemaCache _ = db.Model(&MyModel{}).Statement modelType := reflect.TypeOf(&MyModel{}).Elem() fullName := modelType.PkgPath() + "." + modelType.Name() if v, ok := db.SchemaCache.Load(fullName); ok { cachedSchema := v.(*schema.Schema) for _, field := range cachedSchema.Fields { println("字段名:", field.Name, "对应PostgreSQL类型:", field.DataType) } }
验证说明
你的CustomType已经实现了GormDataType()方法,符合Gorm的GormDataTypeInterface接口规范,ParseField解析时会自动调用该方法,将FirstField的DataType设为numeric,和你预期的结果完全一致。
内容的提问来源于stack exchange,提问作者Irina Stanescu
相关产品推荐
相关产品推荐

