需用 gorm:"column:username" 显式指定列名,避免静默失败;主键与唯一索引不冲突但冗余;size 是字符串快捷写法,type 更底层;嵌套结构体须手动扁平化或忽略。

gorm.Model 结构体字段名和数据库列名不一致怎么办
直接加 gorm tag,别依赖默认映射。GORM 不会自动把 UserName 转成 user_name,除非你明确告诉它怎么转。
常见错误是只写 json:"user_name",结果数据库还叫 user_name,但 GORM 仍查 user_name 字段——这没问题;但如果数据库列其实是 username,而结构体字段是 UserName,又没加 gorm:"column:username",那就查不到数据,也不报错,静默失败。
-
gorm:"column:username"强制指定列名,最常用也最安全 -
gorm:"name:username"是旧版写法(v1.9 以前),v2 已废弃,别用 - 如果字段名本身是
CreatedAt、UpdatedAt这类 GORM 内置时间字段,加gorm:"autoCreateTime"或gorm:"autoUpdateTime"才能触发自动赋值 - 别在
gormtag 里混用json或form等其他 tag 的逻辑,GORM 只认自己的 key
gorm:"primaryKey" 和 gorm:"uniqueIndex" 同时存在会冲突吗
不会冲突,但语义上可能重复或误导。主键天然唯一,再加 uniqueIndex 是冗余的,而且某些数据库(如 MySQL)建表时会多建一个索引,浪费空间。
真实场景中容易踩的坑是:误把业务唯一约束当主键用,比如用 order_no 当主键,又加 uniqueIndex,结果迁移时报错“duplicate primary key”或者生成 SQL 失败。
立即学习“go语言免费学习笔记(深入)”;
-
gorm:"primaryKey"表示该字段是主键,GORM 会自动设为 NOT NULL + AUTO_INCREMENT(整型)或 UUID(字符串) -
gorm:"uniqueIndex"仅建唯一索引,字段可以为空(NULL),但同一张表里不能有两条非 NULL 值相同的记录 - 如果想让非主键字段强制非空且唯一,得同时写
gorm:"not null;uniqueIndex" - PostgreSQL 对 NULL 值的唯一索引处理和 MySQL 不同(允许多个 NULL),跨数据库迁移时要注意
gorm:"type:varchar(255)" 和 gorm:"size:255" 有什么区别
size 是 GORM v2 的快捷写法,只对字符串类型生效,底层仍转成 varchar(255);而 type 是原始 SQL 类型定义,更底层、更自由,但也更容易出错。
典型问题:有人写 gorm:"type:text;size:1000",以为能限制长度,其实 text 类型不支持长度参数,MySQL 忽略 size,PostgreSQL 直接报错。
-
gorm:"size:255"→ 自动推导为varchar(255)(MySQL/SQLite)或character varying(255)(PostgreSQL) -
gorm:"type:jsonb"(PostgreSQL)或gorm:"type:json"(MySQL 5.7+)必须用type,size无效 - 数值类型如
int、float64加size没意义,GORM 不识别,会被忽略 - 使用
type时,确保目标数据库支持该类型,否则 migrate 会失败
嵌套结构体字段怎么映射到单表字段
GORM 不支持自动展开嵌套结构体映射到单表列,比如 User.Profile.Name 不会变成 profile_name。必须手动扁平化,或用自定义 Getter/Setter + gorm:"-" 跳过嵌套字段。
常见错误是把 Profile 定义成 struct 类型字段,又没加 gorm:"-",导致 GORM 尝试建关联表,结果迁移失败或查出空对象。
- 用
gorm:"-"显式忽略嵌套字段:Profile Profile `gorm:"-"` - 把需要映射的字段提出来单独定义:
ProfileName string `gorm:"column:profile_name"` - 如果真要存 JSON 字符串(如整个 profile 存为 JSON),用
gorm:"type:json"+json.RawMessage或自定义类型实现 Scan/Value 方法 - 别依赖
gorm:"embedded"来做字段前缀,它只对嵌入结构体有效(type User struct { BaseModel }),不是嵌套字段
字段 tag 看似简单,但实际项目里最容易出问题的是混合了多种 ORM 行为:自动时间、软删除、JSON 序列化、数据库类型、索引策略……它们之间没有优先级文档,全靠实测。建议每个新 tag 都配一个最小可运行 migration + 查询验证,而不是堆砌一堆 tag 后等上线才暴露问题。










