用 gorm:"-" 标签可彻底跳过字段映射,使该字段不建表、不参与任何crud操作;注意“-”后必须有空格,否则解析失败仍会映射。

用 gorm:"-" 标签跳过字段映射
想让某个字段(比如明文密码、临时缓存字段)完全不参与数据库读写,最直接的方式是在结构体字段上加 gorm:"-" 标签。注意:- 后面必须跟一个空格,否则 GORM 解析失败,该字段仍会被映射。
-
gorm:"-"会彻底忽略该字段——既不建表列,也不在Create/Update/Select中出现 - 适用于敏感字段(如
PasswordPlain)、运行时计算字段(如FullName)、或仅用于 API 层的 DTO 字段 - 不要和
gorm:"default:0"或其他标签混用在同一行,否则可能被误解析
Omit 和 Select 是运行时控制,不是模型定义
Omit 和 Select 是链式方法,只影响单次操作,和结构体标签无关。它们不会改变模型定义,也不会跳过字段建表。
-
db.Omit("Password").Create(&user):插入时跳过Password字段,但表里仍有该列(前提是模型里没加gorm:"-") -
db.Select("Name", "Email").Find(&users):只查这两列,但结果结构体中其他字段(如ID)会被置零,不会报错 - 若结构体字段名与数据库列名不一致(如字段叫
UserName,列叫user_name),又没配gorm:"column:user_name",Select返回的值会映射为空
嵌入结构体时字段忽略容易失效
当用匿名嵌入(如 gorm.Model)时,子结构体里的 gorm:"-" 依然生效,但如果你额外嵌入了带字段的结构体(比如 BaseModel),而它内部字段没加 gorm:"-",那些字段仍会被映射。
- 嵌入结构体默认开启前缀(如
BaseModel的ID变成base_model_id),除非显式设gorm:"embedded" - 如果
BaseModel里有CreatedAt time.Time且你不想存库,不能只在最终模型里加gorm:"-",必须在BaseModel定义时就加 - 字段名含下划线(如
User_Name)不会自动转成user_name;GORM 只做驼峰→下划线推导(UserName→user_name),反向不成立
字段名大小写和 column 标签不匹配会导致静默丢数据
用 Select 查询指定列后,如果结构体字段没配 gorm:"column:xxx",GORM 会按字段名(首字母大写)去匹配列名(通常是小写加下划线),大小写不一致就映射失败,值为零值,不报错也不警告。
- 例如查
"id,name",结构体字段是ID uint,但没写gorm:"column:id"→ID始终为 0 - 用
Scan替代Find可绕过这个问题,但需配合匿名结构体:var res []struct{ ID uint `gorm:"column:id"` Name string `gorm:"column:name"` } - 不要对已有模型直接
db.Table("users").Select("id").Scan(&user),缺失字段可能触发 panic(尤其指针字段)
gorm:"-" 是定义阶段的硬性排除,而 Omit/Select 是运行时柔性控制。两者目标不同,混用时容易误以为“加了 Omit 就等于字段不存在”,结果表里还留着冗余列,或者迁移时意外创建敏感字段。











