gorm模型需严格遵循命名与标签规范:必须用驼峰命名(如createdat),由gorm自动转蛇形;非标列名须显式声明gorm:"column:xxx";嵌入gorm.model前需确认主键类型匹配;关联字段必须显式标注foreignkey;自定义类型须实现valuer和scanner接口。

直接说结论:GORM 模型不是随便写个 struct 就能用的,字段命名、标签、嵌入方式稍有偏差,就会导致表名错、列名错、主键失效、时间字段不自动更新,甚至查询返回空值。
字段命名不按蛇形会导致列名映射失败
GORM 默认把 UserName 映射成 user_name,但如果你写成 username(全小写)或 UserName(驼峰),它仍会尝试转成蛇形,可一旦结构体里混用风格,比如同时存在 Email 和 phone_number,GORM 就无法统一推导,最终生成的 SQL 列名可能和实际表结构对不上。
- 始终用 Go 风格的驼峰命名(如
CreatedAt、MemberNumber),让 GORM 自动转蛇形 - 避免手动拼蛇形字段名(如
user_name)作为字段名,这会让 GORM 误以为你想要一个叫user_name的列,而不是映射UserName - 若必须用非标准列名,显式加
gorm:"column:custom_field"标签,而不是改结构体字段名
gorm.Model 嵌入不是必须的,但漏掉关键字段会丢功能
嵌入 gorm.Model 是最快捷的方式,它自带 ID、CreatedAt、UpdatedAt、DeletedAt 四个字段及其默认行为。但很多人只复制了 gorm.Model 却没注意它内部的 ID 类型是 uint,而你的业务可能需要 int64 或 string 主键 —— 这时直接嵌入反而埋雷。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 如果主键类型/名称不符合业务(比如用 UUID 当主键),别嵌入
gorm.Model,而是自己定义字段并打gorm:"primaryKey" -
CreatedAt和UpdatedAt字段类型必须是time.Time(或其别名),否则 GORM 不会自动赋值 - 想禁用软删除?别删
DeletedAt字段,而是用gorm:"index"替代gorm.DeletedAt,或在迁移时跳过该字段
关联字段不加外键标签会导致 JOIN 失败
GORM 不会自动识别“哪个字段是外键”。比如 User 有个 Profile 字段,你写了 Profile Profile,但它不知道该用 Profile.UserID 还是 Profile.ID 去关联 —— 默认它会找 profile_id,而你的 Profile 表里根本没有这个字段。
- 一对一关联,外键字段必须显式声明:
UserID uint `gorm:"foreignKey:UserID"` - 一对多时,子表结构体里要带外键字段(如
Order里的UserID uint),且父表字段名需匹配(User的ID是uint,那Order.UserID也得是uint) - 别依赖 GORM 的“自动推断”,尤其是当字段名不标准(比如叫
owner_id而不是user_id)时,一定加gorm:"foreignKey:OwnerID"
自定义类型不实现 Scanner / Valuer 会导致 Scan 失败
当你用 *string、sql.NullString 或自定义枚举类型时,GORM 能处理;但如果你写了个 type Status int 并直接放结构体里,GORM 在 Scan 时会 panic:“cannot assign” —— 因为它不知道怎么把数据库的 INT 值塞进你的自定义类型。
- 所有自定义类型,只要用在模型字段中,必须实现
driver.Valuer(写入)和sql.Scanner(读取) -
*string和sql.NullString是安全的,它们已实现这两个接口;string本身也是,但不能表达“NULL”语义 - 时间字段慎用
*time.Time:GORM 对nil时间的处理不稳定,建议统一用time.Time+gorm:"default:current_timestamp"
最常被忽略的其实是字段类型和数据库类型的隐式匹配:比如 Go 的 int 对 MySQL 的 INT 没问题,但对 PostgreSQL 的 BIGINT 就可能溢出;float64 在 SQLite 里存成 REAL,但在某些驱动下精度会丢。模型定义不是写完就完事,得看迁移生成的 DDL 是否真和你预期一致。










