必须显式在 dsn 中添加 parsetime=true 才能生成 time.time 字段,否则 mysql 的 timestamp/datetime 会被解析为 []byte;generatemodel 按表名精准生成,generatealltable 会遍历所有表(含元数据表)易失败;生成代码仅提供类型安全骨架,事务、软删除、预加载仍需手动处理。

直接上手 gorm.io/gen 不需要先搞懂 GORM 全部特性,但必须绕开几个连接和生成阶段的硬性门槛——否则会卡在“没报错却没生成文件”或“结构体字段全是 interface{}”这种问题上。
为什么 parseTime=True 是生成 time.Time 字段的生死线
MySQL 的 TIMESTAMP 和 DATETIME 默认被 gorm.io/gen 解析为 []byte,不是 time.Time。这不是 bug,是驱动层未启用时间解析的必然结果。
-
dsn中必须显式带上&parseTime=True,漏掉大小写(比如写成parsetime=true)也不行 - 如果还用了
loc=Local,记得加在同一个dsn里,否则时区可能出偏移 - 用
mysql.Open(dsn)连接时,gorm.Open()内部不会帮你补这个参数,得自己写全
GenerateModel 和 GenerateAllTable 的实际差异在哪
两者输出结构一致,但触发逻辑和可控性完全不同。别指望 GenerateAllTable() 能自动跳过中间表或历史表。
-
GenerateModel("users"):只读取INFORMATION_SCHEMA.COLUMNS中users表的字段定义,生成一个User结构体 + 对应Query方法 -
GenerateAllTable():遍历当前库所有表,包括schema_migrations、flyway_schema_history这类元数据表——它们往往字段不规范,会导致生成失败 - 更稳妥的做法是:
g.GenerateModel("users", gen.FieldIgnore("deleted_at")),手动屏蔽软删除字段,避免后续查询漏加Unscoped()
生成后不能直接用的三个关键断层
gen 输出的是模型骨架和类型安全的查询 DSL,不是即插即用的业务层代码。很多团队踩坑是因为默认认为 “生成完就能查”。
- 事务没包进去:
q.User.Create()是裸执行,高并发写入需自行套db.Transaction(func(tx *gorm.DB) error { ... }) - 软删除未过滤:
deleted_at IS NOT NULL不会自动加进 WHERE 条件,查列表时得显式调q.User.WithContext(ctx).Unscoped().Find() - 关联预加载要手动配:
q.User.Preload(q.User.Orders)不会自动展开,且外键字段名(如user_id)不会变成UserID,除非你加了gen.FieldRename("user_id", "UserID")
真正省时间的地方,是把“字段类型对齐”和“基础 CRUD 方法签名”从人脑校验变成编译期检查;但数据库权限配置、事务粒度、软删语义这些,还得你亲手定规则。











