Gin 本身不处理数据库,整合 SQLite 的关键在 gorm.Open + sqlite.Open;dsn 必须是文件路径(如 "todo.db"),目录须预先存在,推荐加 "?_fk=1&cache=shared" 启用外键和共享缓存,并启用 WAL 模式防锁库。

直接说结论:Gin 本身不处理数据库,整合 SQLite 的关键在 gorm.Open + sqlite.Open,不是 Gin 配置,也不是路由写法 —— 错把 Gin 当数据库入口,是新手最常卡住的地方。
怎么用 GORM 连上 SQLite 文件(非内存模式)
SQLite 连接本质是 GORM 的事,Gin 只负责把请求转发给业务逻辑。真实可落地的连接方式是:
-
dsn必须是文件路径,比如"todo.db"或./data/app.db;用file:xxx.db前缀反而容易出错(某些 GORM 版本会忽略或解析异常) - 首次运行时,SQLite 会自动创建文件,但目录必须存在 —— 如果
./data/不存在,gorm.Open不报错,但后续AutoMigrate会 panic:“no such file or directory” - 推荐显式加参数确保行为一致:
"todo.db?_fk=1&cache=shared",其中_fk=1启用外键约束,cache=shared支持多连接并发读写(否则默认 private 模式下多个 goroutine 写会报database is locked)
为什么 AutoMigrate 不生效或表没建出来
常见现象是程序跑完没报错,但 SQLite 文件里空空如也 —— 根本原因不是 SQL 写错了,而是 GORM 实例没传下去或模型没注册。
- 确保
db.AutoMigrate(&User{})在gorm.Open成功之后调用,且db是同一个实例(别在函数里重新Open一次) - 模型结构体必须导出字段(首字母大写),且至少有一个字段带
gormtag 或嵌入gorm.Model;纯小写字段如name string不会被映射到列 - 如果用了自定义主键(比如
ID uint而非gorm.Model),要手动加 tag:ID uint `gorm:"primaryKey"`,否则 GORM 无法识别主键,AutoMigrate会跳过该表
CRUD 接口里 db 实例怎么安全传递
Gin 的 Context 不该存 DB 实例(违反依赖注入原则,也难测),正确做法是把 *gorm.DB 作为依赖注入到 handler 函数闭包里。
- 别这么写:
r.GET("/user", func(c *gin.Context) { db := gorm.Open(...) })—— 每次请求都新建连接,资源泄漏 - 应该初始化一次 DB,然后绑定到 handler:
handler := NewUserHandler(db); r.GET("/user", handler.List) - 如果图省事用闭包,确保
db是外部变量:r.GET("/user", func(c *gin.Context) { db.Create(&u) }),但要注意全局变量在并发下线程安全(*gorm.DB本身是 safe 的)
最容易被忽略的是 SQLite 的 WAL 模式和事务隔离级别 —— 默认 DELETE 模式下高并发写容易卡住,上线前至少加 ?_journal=WAL 到 DSN,并在 handler 里用 db.Transaction() 显式控制边界,而不是靠 defer 或裸调用。











