

新闻资讯
技术学院gorm.Open 必须传入对应驱动的 Dialector 实例,如 mysql.Open(dsn),不可传字符串;Model 字段需显式标注 primaryKey 或 column;Where 条件中零值默认被忽略;事务内需用 tx.WithContext(ctx) 传递上下文。
Go 语言中 gorm.Open 不是自动识别数据库类型的,它依赖你传入的 gorm.Dialector 实例。直接传字符串(比如旧版写法 gorm.Open("mysql", ...))在 v2+ 已被移除,硬写会编译失败。
常见错误现象:报错 undefined: gorm.Open 或 cannot use "xxx" (type string) as type gorm.Dialector。
mysql.Open(dsn),来自 gorm.io/driver/mysql
postgres.Open(dsn),来自 gorm.io/driver/postgres
sqlite.Open(file),注意参数是文件路径,不是 DSN别漏掉 import 对应驱动包,否则 Open 函数根本不存在。
GORM 不会默认把 Go 字段名转成 snake_case 数据库列名,除非你显式配置或加标签。比如 UserName 默认映射到 user_name 是因为 GORM 内置了蛇形命名策略,但一旦你写了 json:"user_name" 却没写 gorm:"column:user_name",GORM 仍可能生成 user_name 列——但这是巧合,不是保证。
gorm:"primaryKey",否则 GORM 可能选错字段甚至报错 failed to find primary field
gorm:"-:all" 或 gorm:" 控制读写权限
gorm:"autoCreateTime;autoUpdateTime",避免手动赋值 time.Now()
没有标签时,GORM 的默认行为受全局 NamingStrategy 影响,不同版本策略有差异,别依赖“好像能用”。
手写 SQL 拼接字符串(如 "WHERE name = '" + name + "'")不仅易 SQL 注入,还绕过了 GORM 的预处理和类型转换。GORM 的 Where 支持多种写法,底层都走参数化查询。
db.Where("age > ?", 18).Find(&users)
db.Where("name LIKE ?", "%john%").Find(&users)
db.Where("status = ? AND role = ?", "active", "admin"
).Find(&users)
db.Where(&User{Status: "active", Role: "admin"}).Find(&users) // 结构体条件
注意:Where 后跟 map 或结构体时,零值(如 0, "", nil)默认会被忽略;如果真要查 age = 0,得用 Where("age = ?", 0)。
另外,First() 和 Take() 行为不同:First() 按主键升序,Take() 不保证顺序,查单条时别混用。
单纯用 db.Transaction(func(tx *gorm.DB) error { ... }) 创建的事务内部,无法响应 context.Context 的 cancel 或 timeout。如果事务卡住(比如锁等待),整个 goroutine 就挂死。
tx 显式带上 context:tx.WithContext(ctx).Where(...).Update(...)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
db 实例,否则 context 不生效还有一个容易被忽略的点:事务内执行 Create 后,如果结构体带自增主键,GORM 会把生成的 ID 回填到原变量,但这个回填只发生在事务成功提交后——若事务 rollback,ID 字段不会还原,业务层需自行清理或重置。