Golang使用gorm连接数据库并操作数据

11次阅读

gorm.Open 必须传入对应驱动的 Dialector 实例,如 mysql.Open(dsn),不可传字符串;Model 字段需显式标注 primaryKey 或 column;Where 条件中零值默认被忽略;事务内需用 tx.WithContext(ctx) 传递上下文。

Golang使用gorm连接数据库并操作数据

gorm.Open 传参顺序和驱动名必须严格匹配

Go 语言中 gorm.Open 不是自动识别数据库类型的,它依赖你传入的 gorm.Dialector 实例。直接传字符串(比如旧版写法 gorm.Open("mysql", ...))在 v2+ 已被移除,硬写会编译失败。

常见错误现象:报错 undefined: gorm.Opencannot use "xxx" (type String) as type gorm.Dialector

  • MySQL 必须用 mysql.Open(dsn),来自 gorm.io/driver/mysql
  • postgresql 对应 postgres.Open(dsn),来自 gorm.io/driver/postgres
  • sqlitesqlite.Open(file),注意参数是文件路径,不是 DSN

别漏掉 import 对应驱动包,否则 Open 函数根本不存在。

定义 Model 时字段标签不能只靠 Struct 名称推断

GORM 不会默认把 Go 字段名转成 snake_case 数据库列名,除非你显式配置或加标签。比如 UserName 默认映射到 user_name 是因为 GORM 内置了蛇形命名策略,但一旦你写了 json:"user_name" 却没写 gorm:"column:user_name",GORM 仍可能生成 user_name 列——但这是巧合,不是保证。

立即学习go语言免费学习笔记(深入)”;

  • 主键必须明确:加 gorm:"primaryKey",否则 GORM 可能选错字段甚至报错 failed to find primary field
  • 想跳过某字段不映射:用 gorm:"-:all"gorm:" 控制读写权限
  • 时间字段推荐用 gorm:"autoCreateTime;autoUpdateTime",避免手动赋值 time.Now()

没有标签时,GORM 的默认行为受全局 NamingStrategy 影响,不同版本策略有差异,别依赖“好像能用”。

Query 时用 Where 链式调用比拼接 SQL 更安全也更灵活

手写 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.WithContext(ctx) 传递超时或取消信号

单纯用 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 字段不会还原,业务层需自行清理或重置。

text=ZqhQzanResources