当前位置: 首页 > news >正文

GORM的字段类型推导源码解析

字段类型的推导原理

摘要:本文详细解析了 GORM 中字段类型映射到数据库类型的完整推导过程。核心结论是:当 Go 结构体字段为int类型且未显式指定size标签时,GORM 会根据其Kind推导出Size=64,最终在 MySQL 中映射为bigint。推导的优先级为:1) 显式SIZE标签;2) 根据 Go 类型推导DataType;3) 显式TYPE标签(可能覆盖DataType);4) 若Size仍为 0,则根据 Go 类型推导Size。最终,DataTypeSize共同决定数据库中的具体类型(如intbigint)。

😀为什么我PeopleModel.Age,在gorm标签里写的type:int,为什么生成的表是bigint? 首先,gorm会根据数据类型DataType和长度Size判断这个字段在数据库表里应该用什么类型。1.没有指定size,gorm会根据DataType进行反推,源码如下,goint对应的size=64,对应到mysql里就是bigintiffield.Size==0{switchreflect.Indirect(fieldValue).Kind(){casereflect.Int,reflect.Int64,reflect.Uint,reflect.Uint64,reflect.Float64:field.Size=64casereflect.Int8,reflect.Uint8:field.Size=8casereflect.Int16,reflect.Uint16:field.Size=16casereflect.Int32,reflect.Uint32,reflect.Float32:field.Size=32}}2.指定了Size,比如:Ageint`gorm:"size:32"`,int32这个长度,在mysql里对应int.综上,Size的来源有两种:标签size显式指定、gorm根据反射推导。 ┌────────┬────────────────────────┬────────────────────────────────────────────┐ │ 优先级 │ 来源 │ 例子 │ ├────────┼────────────────────────┼────────────────────────────────────────────┤ │1│ SIZE 标签 │ gorm:"size:32"→ field.Size=32│ ├────────┼────────────────────────┼────────────────────────────────────────────┤ │2│ Go 类型的 reflect.Kind │int64,int3232,int1616,int88│ └────────┴────────────────────────┴────────────────────────────────────────────┘3.field.Size 的确定 SIZE 标签存在? ├─ 是 → 用 SIZE 标签的值 └─ 否 → 根据 Go 类型推断:int/int64/uint/uint64/float6464int8/uint88int16/uint1616int32/uint32/float3232field.DataType 的确定 TYPE 标签存在? ├─ 是 → 匹配 schema 常量(int/uint/bool/float/string/time/bytes)? │ ├─ 是 → 用该常量(后续走GORM 内部映射,会参考 Size) │ └─ 否 → 当自定义类型原样透传给数据库,相当于跳过了gorm └─ 否 → 根据 Go 类型推断(int→Int,string→String...4.当datatype和size都没有,gorm先推导哪个?1.读 SIZE 标签 → field.Size2.推导 Go 类型 → field.DataType3.读 TYPE 标签覆盖 → field.DataType4.Size 还是0? → 根据 Go 类型推导 field.Size5.既然先datatype后size,那么size的推导是根据字段后的类型,还是datatype? 是根据字段后的类型,源码如图iffield.Size==0{switchreflect.Indirect(fieldValue).Kind(){// ← 看的是 Go 类型casereflect.Int,reflect.Int64,reflect.Uint,reflect.Uint64,reflect.Float64:field.Size=64casereflect.Int8,reflect.Uint8:field.Size=8casereflect.Int16,reflect.Uint16:field.Size=16casereflect.Int32,reflect.Uint32,reflect.Float32:field.Size=32}}
//根据type标签得到DataTypeifval,ok:=field.TagSettings["TYPE"];ok{lowerVal:=DataType(strings.ToLower(val))switchlowerVal{caseBool,Int,Uint,Float,String,Time,Bytes:field.DataType=lowerVal// ← 匹配到常量,走这里default:field.DataType=DataType(val)// ← 没匹配到,走这里}}//field 第 233 行:如果没写type,会根据 Go 类型推导 DataTypeswitchreflect.Indirect(fieldValue).Kind(){casereflect.Int,reflect.Int8,reflect.Int16,reflect.Int32,reflect.Int64:field.DataType=Int...}
//根据DataType选择对应的类型switchfield.DataType{caseschema.Bool:return"boolean"caseschema.Int,schema.Uint:returndialector.getSchemaIntAndUnitType(field)caseschema.Float:returndialector.getSchemaFloatType(field)caseschema.String:returndialector.getSchemaStringType(field)caseschema.Time:returndialector.getSchemaTimeType(field)caseschema.Bytes:returndialector.getSchemaBytesType(field)default:returndialector.getSchemaCustomType(field)//里面是sqltype := string(field.DataType)}
//根据Size的大小选择对应的类型长度func(dialector Dialector)getSchemaIntAndUnitType(field*schema.Field)string{switch{casefield.Size<=8:returnconstraint("tinyint")casefield.Size<=16:returnconstraint("smallint")casefield.Size<=24:returnconstraint("mediumint")casefield.Size<=32:returnconstraint("int")default:returnconstraint("bigint")// ← 你的 Age 走到了这里}}
http://www.jsqmd.com/news/1125458/

相关文章:

  • 1.逻辑结构与逻辑工程学
  • 【电赛/毕设终极杀器】超越 PID 与 LQR!控制界的黑魔法:自抗扰控制 (ADRC) 原理与 STM32 硬核部署指南
  • 基于51单片机的火灾报警系统设计 智能烟雾报警器温度检测21(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_
  • C盘清理工具合集 Windows系统垃圾深度清理 磁盘瘦身 下载
  • YOLO11视频目标检测实战:从环境配置到高级应用
  • Engine-Sim技术深度解析:实时发动机模拟与音频合成的工程实现
  • NSK滚珠丝杠W3205SS技术解析
  • Dify新手入门:从账号界面到AI工作流实战指南
  • 手把手教你用8款一键生成论文工具,极速搞定各类论文
  • Agent 架构
  • 基于PyTorch与UrbanSound8K数据集的环境声音分类实战
  • 智能项目管理周报:AI 可以汇总状态,不能替代判断
  • SRS 4.0 HTTP回调实战:SpringBoot 实现 7 种事件鉴权与业务集成
  • Vite 环境变量治理:别把构建时配置当运行时开关
  • Linux syslog日志权限出错
  • Wishbone BFM 设计与实现:从手写总线到自动化自检
  • 什么叫Padding Oracle
  • 说说程序员、博客、论坛及个人专业相关知识的提高
  • 基于大数据Hadoop+Spark的汽车销售数据分析系统设计与实现任务书
  • Claude Code 封号与“隐藏标记“争议:一份基于公开资料的核验清单
  • 用 QClaw + SQL Server 搭建私有企业知识库——中小企业的“有边界记忆”方案
  • 基于STM32单片机智能窗帘窗户光敏定时遥控温湿度语音物联网设计12(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_
  • 大文件分片上传完整案例
  • 网页自动化实战指南:从零构建高效工作流
  • 苏州本地GEO获客标杆!环境工程企业AI全域收录破5.2万条
  • 【学生调研报告】网上银行安全架构与安全方案研究
  • 从零构建系统工具:先写验收脚本,再补漂亮交互
  • 无货源自动拍单发货软件靠谱吗?新手先看货源关联和规格匹配一件代发工具教程解析
  • 课堂教学PPT模板推荐哪家?这6个平台教师亲测可用
  • 来博客园的基本是写程序的,好像是废话,缩小点范围,来这里起嘛证明,大家都想学习进步,都是同道中的同道中人。兴趣,往高一点说叫理想,是我们共同的动力,从上一文中再次得到印证。