GORM 结构体字段标签(Struct Tags)详解

一、GORM 模型字段标签基础语法

GORM 使用 struct tag 定义字段行为:

Go 复制代码
type User struct {
    FieldName DataType `gorm:"tag1:value1;tag2:value2" json:"field_name"`
}

优先级(从高到低):

  1. gorm:"..." 主控制标签(数据库行为)

  2. 其他标签(json、form 等)

  3. 结构体字段名作为默认列名(SnakeCase)


二、字段标签分类与详解(最重要部分)

1. 基本字段标签

(1) column(指定数据库列名)

Go 复制代码
gorm:"column:user_name"

(2) type(指定数据库字段类型)

Go 复制代码
gorm:"type:varchar(100)"

(3) primaryKey(主键)

Go 复制代码
gorm:"primaryKey"

(4) autoIncrement(自增)

与 primaryKey 组合常用。

Go 复制代码
gorm:"primaryKey;autoIncrement"

(5) unique / uniqueIndex(唯一约束)

Go 复制代码
gorm:"unique" // 单字段唯一 
gorm:"uniqueIndex" // 创建唯一索引 
gorm:"uniqueIndex:idx_name" // 复合唯一索引

(6) index(普通索引)

Go 复制代码
gorm:"index" // 单字段索引 
gorm:"index:idx_name" // 指定索引名 
gorm:"index:idx_name,priority:1" // 复合索引顺序

(7) size(字符串长度)

Go 复制代码
gorm:"size:255"

(8) default(默认值)

Go 复制代码
gorm:"default:0"
gorm:"default:'unknown'"

(9) not null(非空)

Go 复制代码
gorm:"not null"

(10) <- / ->(字段读写权限)

控制 GORM 是否对该字段进行写入或读取:

Go 复制代码
gorm:"<-:create"          // 仅创建时写入
gorm:"<-:update"          // 仅更新时写入
gorm:"<-:false"           // 禁止写入
gorm:"->:false"           // 查询不读该字段
gorm:"-:"                // 读写都禁用
gorm:"-"                 // 完全忽略该字段

2. 时间相关标签(CreateAt/UpdatedAt)

(1) autoCreateTime(创建自动填充)

Go 复制代码
gorm:"autoCreateTime"
gorm:"autoCreateTime:milli" // 毫秒
gorm:"autoCreateTime:nano"  // 纳秒

(2) autoUpdateTime(更新自动填充)

Go 复制代码
gorm:"autoUpdateTime"
gorm:"autoUpdateTime:milli"
gorm:"autoUpdateTime:nano"

3. 外键 / 关联关系标签

(1) foreignKey(外键字段)

Go 复制代码
gorm:"foreignKey:UserID"

(2) references(指定关联的字段)

Go 复制代码
gorm:"references:ID"

(3) constraint(外键约束)

Go 复制代码
gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"

(4) many2many(多对多中间表)

Go 复制代码
gorm:"many2many:user_roles"

(5) polymorphic(多态关联)

Go 复制代码
gorm:"polymorphic:Owner"

4. Serializer(序列化字段)

适用于 JSON、MsgPack 等类型存储。

(1) 保存为 JSON

Go 复制代码
gorm:"serializer:json"

示例:

Go 复制代码
type User struct {
    Hobbies []string `gorm:"serializer:json"`
}

5. Embedded / EmbeddedPrefix(嵌入字段)

(1) embedded(字段嵌入,不创建嵌套)

Go 复制代码
gorm:"embedded"

(2) embeddedPrefix(嵌入字段添加前缀)

Go 复制代码
gorm:"embeddedPrefix:user_"

6. comment(字段注释)

Go 复制代码
gorm:"comment:'用户年龄'"

三、字段标签使用示例(非常完整)

下面是一个实际业务级别的模型,涵盖各种标签。

Go 复制代码
type User struct {
    ID        uint           `gorm:"primaryKey;autoIncrement;comment:'主键ID'"`
    UserName  string         `gorm:"column:user_name;type:varchar(50);uniqueIndex;not null;comment:'用户名'"`
    Email     string         `gorm:"type:varchar(100);index:idx_email;not null;comment:'邮箱地址'"`
    Age       int            `gorm:"default:0;comment:'年龄'"`
    Profile   UserProfile    `gorm:"embedded;embeddedPrefix:profile_"`
    Tags      []string       `gorm:"serializer:json;comment:'标签(JSON)'"`
    
    CreatedAt time.Time      `gorm:"autoCreateTime"`
    UpdatedAt time.Time      `gorm:"autoUpdateTime"`
    DeletedAt gorm.DeletedAt `gorm:"index"`
}

type UserProfile struct {
    Address string `gorm:"type:varchar(200)"`
    Avatar  string `gorm:"type:varchar(255)"`
}

四、关联模型完整示例

1. 一对多(User 有多个 Orders)

Go 复制代码
type User struct {
    ID     uint
    Orders []Order `gorm:"foreignKey:UserID"`
}

type Order struct {
    ID     uint
    UserID uint
}

2. 多对多(Users 共享 Roles)

Go 复制代码
type User struct {
    ID    uint
    Roles []Role `gorm:"many2many:user_roles"`
}

type Role struct {
    ID   uint
    Name string
}

五、GORM 中 Tag 的常见坑和注意事项

1. default 只在建表时生效,不影响运行时零值

如果字段是 0 或 "",GORM 不会主动应用 default。

解决方法:

Go 复制代码
Age *int `gorm:"default:18"`

2. 字段必须导出(首字母大写)GORM 才能识别

3. 没有 not null 时,GORM 不会自动加默认非空

4. JSON serializer 必须使用 slice 或 map,不支持 struct 直接存储 unless implement Scanner/Valuer

5. uniqueIndex 必须在 AutoMigrate 后才能生效


六、总结表:最常用的 GORM Tag 清单

标签 作用
column 指定列名
type 指定数据库类型
primaryKey 主键
autoIncrement 自增
unique / uniqueIndex 唯一约束
index 索引
size 字符串长度
default 默认值
not null 非空
<- 写属性
-> 读属性
- 忽略字段
autoCreateTime 创建时间
autoUpdateTime 更新时间
foreignKey 外键字段
references 外键关联字段
many2many 多对多
serializer:json JSON 存储
embedded 内嵌字段
embeddedPrefix 内嵌字段前缀
comment 字段注释
相关推荐
超级架构师9 小时前
PRAXO-CORE 2.5.0:用 conformance 和显式边界构建 Go Agent 框架
开发语言·人工智能·后端·golang·ai编程·智能体框架·praxo-core
我就是全世界13 小时前
OpenCode Go 套餐划算吗:先看你用哪个模型
开发语言·后端·golang
小杨互联网16 小时前
Go 现代 CLI 工具离线镜像合集
开发语言·后端·golang·开源·go·命令行
hourinX18 小时前
从直接填格子到筛选图案:头像生成这部分是怎样改过来的—— gdenticon 重构日志(三)
go
microrain19 小时前
跟着一条属性报文走一遍 SagooIoT 的接入链路
物联网·架构·golang·sagooiot
CodeGL19 小时前
微服务框架——go-zero
微服务·架构·golang
我不会起名字32221 小时前
Redis 从 0 到 1(十三):分布式锁被误删、锁不住?Go 无 Lua 实现 3 级防御
redis·go·分布式锁·watch·setnx
hourinX2 天前
从 v1 到 v2,我重新拆了头像生成的整条链路—— gdenticon 重构日志(二)
go
紧跟先前的步伐2 天前
Go AI Agent 实战 22|完善 Agent 执行循环:从工具调用到最终回答
人工智能·ai·golang
后台模板学习2 天前
Go Web开发中任务调度框架的源码解析与高可用实现方案
开发语言·后端·golang