Iris框架整合GORM需全局单例初始化并注册为应用值:启动时用sync.Once确保gorm.Open仅执行一次,配置连接池参数(SetMaxOpenConns等)后通过app.RegisterValue(gorm.DB, db)挂载;handler中用ctx.Values().Get("gorm.DB").(*gorm.DB)安全获取;User结构体须实现TableName()返回真实表名,主键字段标注gorm:"primaryKey",Find操作必须传指针切片。

如何在 Iris 启动时初始化 GORM 并挂载到 App
不能在每个 handler 里重复 gorm.Open,必须全局单例初始化,并通过 iris.Application.RegisterValue 或自定义容器注入。常见错误是把 *gorm.DB 直接作为包级变量裸露使用,导致测试难、事务难控、连接池配置失效。
- 用
func() *gorm.DB包裹初始化逻辑,确保只执行一次(配合sync.Once或直接放init()) - 调用
db.DB().SetMaxIdleConns和db.DB().SetMaxOpenConns必须在gorm.Open之后、首次使用前完成 - 别漏掉
db.DB().SetConnMaxLifetime(time.Hour),MySQL 默认 wait_timeout=28800 秒(8 小时),但连接空闲超时会断连,设为 1 小时更稳 - Iris 中推荐注册为值:
app.RegisterValue((*gorm.DB)(nil), db),handler 里用ctx.Values().Get("*gorm.DB").(*gorm.DB)取
为什么 User{} 结构体要实现 TableName 方法而不是依赖默认命名
GORM 默认把 User 映射成表名 users,但 Iris 项目常对接已有数据库,表名可能是 t_user 或 sys_user。不显式控制,AutoMigrate 会建错表,Find 会查空结果,且错误不报——它默默去查 users 表,而你根本没建。
- 加方法:
func (User) TableName() string { return "t_user" } - 如果表名带 schema(如
mydb.t_user),返回"mydb.t_user"即可,GORM 会原样拼进 SQL - 注意:该方法必须定义在值接收者上(
(User)),指针接收者((*User))在某些版本中不生效
在 Iris handler 里做 Create/Update 时,为什么 db.Create(&u) 返回的 ID 总是 0
这不是 Iris 的问题,是 GORM 模型字段标签没配对主键或类型不匹配。最常见的是用了 int 但数据库是 BIGINT UNSIGNED,或漏了 gorm:"primaryKey"。
- 检查结构体字段:
ID uint `gorm:"primaryKey;autoIncrement"`(推荐uint而非int,避免负值) - 若用复合主键,必须全部字段加
gorm:"primaryKey",且Create后不会自动赋值回结构体 -
Create成功后立刻读u.ID是安全的,但前提是没用Omit("id")或Select()过滤掉主键字段 - 调试技巧:开启 GORM 日志,
gorm.Config{Logger: logger.Default.LogMode(logger.Info)},看生成的 INSERT 是否含id字段
Query 多条记录时,为什么 Find(&users) 不报错但 users 是空切片
多数情况是传参类型错了:Find 第一个参数必须是指针切片(*[]User),不是切片([]User)也不是结构体指针(*User)。写成 db.Find(&users) 前,users 必须已声明为 var users []User。
- 正确写法:
var users []User; db.Where("age > ?", 18).Find(&users) - 错误写法:
db.Where("age > ?", 18).Find(users)(传值,GORM 无法写入) - 也别写成
db.Where(...).Find(&user)(单个结构体指针),那只会覆盖第一个结果,其余丢弃 - 如果确定只查一条,用
First或Take更明确,Find是专为多条设计的


















