直接嵌入gorm.model可快速起步,但字段名、主键、时间戳不匹配业务表时必须用标签显式覆盖,如column、primarykey、embeddedprefix等,否则易导致列名冲突或标签失效。

直接用 gorm.Model 嵌入是最省事的起点,但字段名、主键、时间戳不匹配业务表时,必须靠标签手动覆盖——别指望默认行为能兜底。
怎么嵌入 gorm.Model 快速起步
它自带 ID、CreatedAt、UpdatedAt、DeletedAt 四个字段,类型和标签已预设好,适合多数 CRUD 场景。
- 结构体字段名必须大写导出,小写字段(如
ignored string)会被 GORM 完全忽略 - 嵌入后无需再声明这四个字段,否则可能类型冲突或漏掉
gorm:"primaryKey" -
DeletedAt默认启用软删除:调用Delete实际是更新该字段,不是物理删行 - 如果数据库列名是
createtime而非created_at,仍需显式加标签:CreatedAt time.Time `gorm:"column:createtime"`
主键和列名不一致时必须加标签
GORM 不会从变量名大小写或注释推断列名,一切以 gorm 标签为准。
- 主键不是
ID?必须显式写gorm:"primaryKey",例如:UserID uint `gorm:"primaryKey"` - 字段名是
UserName,但数据库列是username?加gorm:"column:username" - 字段名含下划线(如
user_name),GORM 默认转驼峰(UserName),但不会反向推导,仍需column显式指定 - 想跳过某个字段(如明文密码)?用
gorm:"-",注意后面有空格,否则解析失败
嵌入结构体时 embeddedPrefix 容易被忽略
用 embedded 把子结构体“摊平”进父结构体很常见,但字段冲突或需区分来源时,embeddedPrefix 是关键。
- 不加前缀:
Address struct{ City string } `gorm:"embedded"`→ 生成列city - 加前缀:
Address struct{ City string } `gorm:"embedded;embeddedPrefix:addr_"`→ 生成列addr_city - 两个嵌入结构体都有
Name字段?不加前缀会导致编译报错或字段覆盖,必须用前缀隔离 -
embeddedPrefix只影响列名,不影响 Go 结构体内存布局或访问方式
常见标签组合和易错点
多个标签用分号 ; 或空格分隔,优先级:gorm:"" > 其他标签(如 json:"") > 默认命名规则。
-
gorm:"size:255;not null;uniqueIndex":定义长度、非空、唯一索引三合一 -
gorm:":false":仅创建时写入,查询时不读(适合加密盐、随机 token 等) -
gorm:"default:0"和gorm:"default:'unknown'":数字不用引号,字符串必须单引号 - 指针字段(如
*string、*time.Time)可存NULL;非指针字段零值(""、0)会被写入,不是NULL
最常被绕过的细节是:字段名大小写、embeddedPrefix 缺失导致列名冲突、gorm:"-" 后多空格或少空格导致标签失效——这些错误在迁移或查询时才暴露,且无明确提示。











