Gorm使用规范&&最佳实践3/4|Go主题月

1,868 阅读2分钟

gorm使用规范和最佳实践,仅做参考

删除

和Update相似,在删除一条记录时,需要指定其主键,因此强制要求删除和where子句一起使用,即使批量删除默认不触发:

db.Delete(&email) // 不建议使用

db.Where("name = ?", "wzy").Delete(&email) // 带额外条件的删除,建议使用

事务控制

在gorm中事务控制会创建一个新的数据库连接,在gorm官网中的事例如下:

// 开始事务
tx := db.Begin()

// 在事务中执行一些 db 操作(从这里开始,您应该使用 'tx' 而不是 'db')
tx.Create(...)

// ...

// 遇到错误时回滚事务
tx.Rollback()

// 否则,提交事务
tx.Commit()

官网中对于数据库连接应该使用tx的提示就不多说了。 对于事务操作在对多个函数进行事务操作的时候,一种比较常见的方式是判断前一个函数是否返回error,如果返回error,则代码中手动进行rollback,例如:

func foo(){
    var err error
    
    tx := db.Begin()
    if err = foo1(tx);err != nil {
        tx.Rollback()
    }
    
    if err = foo1(tx);err != nil {
        tx.Rollback()
    }
    
    tx.Commit()
}

func foo1(dbs...*gorm.DB)error{
}

func foo2(dbs...*gorm.DB)error{
}

每一个分支都有回滚操作不仅不优雅,代码重复率也高。因此建议对于每一种可能出现error的情况,在defer中去从处理error并回滚:

func foo(){
    var err error
    
    tx := db.Begin()
    defer handleError(&err) // 错误处理时统一回滚,如果error不存在则进行提交
    if err = foo1(tx);err != nil {
        return
    }
    
    if err = foo1(tx);err != nil {
        return
    }
    
    return
}

func foo1(dbs...*gorm.DB)error{
}

func foo2(dbs...*gorm.DB)error{
}

handleError函数中负责判断是否在事务过程中产生错误,如果产生则回滚,如果没有产生则提交:

handleError := func(err *error) {
    if *err == nil {
      err = &(tx.Commit().Error)
    }
    if *err != nil {
      tx.Rollback()
    }
}

目前还未发现比较好的场景来使用嵌套事务,欢迎大家补充。