gorm识别字段必须首字母大写,小写字段被静默忽略;需用gorm:"column:xxx"显式映射非标准列名,忽略字段用gorm:"-",主键/时间戳/软删除须显式配置。

字段名必须用大写字母开头才能被GORM识别
GORM通过反射读取结构体字段,只有导出字段(即首字母大写)才会被映射到数据库。如果定义 name string,GORM会完全忽略它;必须写成 Name string。小写字段不会报错,但也不会生成列、不会参与CRUD,容易误以为“模型定义好了”,结果查不到数据或插入为空。
实操建议:
- 所有希望映射到数据库的字段,首字母必须大写
- 若需自定义列名(比如数据库用
user_name,Go里叫Name),用gorm:"column:user_name"标签显式声明 - 不想映射的字段(如临时计算值),用小写 +
gorm:"-"标签双重保险,例如fullName string `gorm:"-"`
主键、时间戳和软删除需要显式配置
GORM不会自动把 ID 当主键,也不会默认启用 CreatedAt/UpdatedAt 或软删除。如果你没配,Create 不会自动填时间,Delete 是物理删除,ID 可能不自增或不被识别为PK。
实操建议:
- 主键:加
gorm:"primaryKey"(推荐)或命名为ID uint(GORM 会尝试识别,但不保证) - 创建/更新时间:字段名必须是
CreatedAt、UpdatedAt,且类型为time.Time;也可自定义名,但要配gorm:"autoCreateTime"等标签 - 软删除:嵌入
gorm.DeletedAt字段,并确保迁移时启用(db.AutoMigrate(&User{})会自动加deleted_at列)
外键关联要同时定义字段和结构体字段,并配好标签
只写 UserID uint 不代表建立了关联;只写 User User 也不自动绑定。GORM需要“外键字段 + 关联字段”成对存在,并靠标签明确关系方向。
实操建议:
- 一对多:在子表结构体中定义外键字段(如
UserID uint)和关联字段(如User User),并用gorm:"foreignKey:UserID"指向它 - 多对多:需中间表结构体,且两边都要用
gorm:"many2many:users_posts;"显式指定表名 - 避免用
int做外键——GORM对uint和int64支持更稳定,int在32位系统可能出错
迁移前务必检查 struct tag 中的 SQL 类型与约束
AutoMigrate 会按 struct tag 生成建表语句,但很多细节不会报错,只静默忽略。比如写 gorm:"type:varchar(100)" 对 SQLite 无效(它不认 type),写 gorm:"uniqueIndex" 却漏了 index 标签,索引就不会建。
实操建议:
- 数据库特异性类型(如
jsonb、uuid)必须配合驱动支持,PostgreSQL 要用pgtype.UUID或第三方类型,不能只靠type:uuid - 非空约束写
gorm:"not null",唯一索引写gorm:"uniqueIndex"(注意不是unique) - 字符串长度限制优先用
size(如gorm:"size:255"),比type:varchar(255)更跨数据库兼容
最常被忽略的是:迁移不会自动修改已存在列的类型或约束,AutoMigrate 只新增列或索引。改字段必须手动 db.Migrator().AlterColumn() 或用原生 SQL。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











