最常见原因是漏掉驱动注册:必须显式导入 _ "gorm.io/driver/sqlite"(带下划线),否则驱动未注册,gorm.Open 报 unsupported driver: sqlite;还需确认使用 v2 官方驱动而非旧版。

为什么 gorm.Open(sqlite.Open("db.db")) 会 panic?
最常见原因是漏掉驱动注册:GORM 不会自动加载 SQLite 驱动,必须显式导入 _ "gorm.io/driver/sqlite"(注意开头的下划线)。只写 "gorm.io/driver/sqlite" 没用——Go 不会执行包里的 init(),驱动就不会注册,gorm.Open 就报 unsupported driver: sqlite。
还要确认版本:GORM v2 要求用 gorm.io/driver/sqlite,不是旧版的 github.com/mattn/go-sqlite3 或 github.com/jinzhu/gorm/dialects/sqlite。如果 go.mod 里出现后者,得删掉并替换成前者。
- 导入必须带下划线:
import _ "gorm.io/driver/sqlite" - 驱动路径必须是
gorm.io/driver/sqlite(v2 官方驱动) - GORM v1.23+ 内置支持,但不启用;v2 必须手动导入才能用
sqlite.Open() 的路径参数怎么写才不踩坑?
sqlite.Open() 接收一个字符串路径,但不同写法行为差异极大,尤其影响开发调试和测试。
- 磁盘文件:
sqlite.Open("app.db")—— 不存在时自动创建,但目录需有写权限;路径建议用绝对路径或确保工作目录可控 - 内存数据库:
sqlite.Open(":memory:")—— 每次调用都是全新实例,进程退出即丢数据;适合单元测试,但别误用于生产 - 带参数的路径:
sqlite.Open("app.db?_journal_mode=WAL&_busy_timeout=5000")—— 参数用&连接(不是 HTML 实体&),_journal_mode=WAL可提升并发写入表现,_busy_timeout避免database is locked
外键、事务、迁移为啥不生效?
SQLite 默认关闭外键约束,也默认不开启 WAL 模式,AutoMigrate 在已有表上改结构还容易静默失败——这些都不是 GORM 的锅,是 SQLite 自身行为。
- 外键必须手动开启:
db.Exec("PRAGMA foreign_keys = ON"),且要在gorm.Open之后、任何模型操作之前执行 - WAL 模式建议开启(尤其多协程写):
sqlite.Open("app.db?_journal_mode=WAL"),否则默认 DELETE 模式下写锁粒度大 -
AutoMigrate对已有表加字段/改类型支持弱,特别是含外键或唯一约束时;开发阶段优先用空 DB 文件重跑迁移,或改用db.Migrator().AddColumn() - 多对多关联表要手动建:
db.SetupJoinTable(&User{}, "Roles", &UserRole{}),否则AutoMigrate可能漏掉
怎么拿到底层 *sql.DB 并设置连接池?
GORM 的 *gorm.DB 是封装层,真正控制连接池的是它底下的 *sql.DB。不调这个,SetMaxOpenConns 等就无效。
- 先取底层对象:
sqlDB, err := db.DB() - 再设连接池:
sqlDB.SetMaxOpenConns(20)、sqlDB.SetMaxIdleConns(10)、sqlDB.SetConnMaxLifetime(60 * time.Second) - SQLite 是文件级数据库,连接池意义不如 MySQL/PostgreSQL 大,但并发读写时仍建议设合理值(比如
MaxOpenConns=10),避免太多句柄争抢文件锁
SQLite 的 PRAGMA 设置、连接池调优、驱动注册这三步,少一个都会让看似简单的连接变成 runtime panic 或行为异常——它们不在文档最前面,但恰恰是实际编码时最先卡住你的地方。


















