golang?db事务的统一封装的实现

 更新时间:2022-01-27 14:15:53   作者:佚名   我要评论(0)

目录简单封装偷懒第一步
偷懒第二步
偷懒第三步
进一步封装事务处理的流程示例




database := db.DB
tx, err := database.Beg

事务处理的流程示例

    database := db.DB
    tx, err := database.Begin()
    if err != nil {
        return err
    }
    stmt, err := tx.Prepare(sqlQuery)
    if err != nil {
        tx.Rollback()
        return err
    }
    _, err = stmt.Exec(paras...)
    if err != nil {
        tx.Rollback()
        return err
    }
    err = tx.Commit()
    if err != nil {
        tx.Rollback()
        return err
    }

以上是我们使用事务时的一般操作,如果每做一次事务的操作均要进行重新写一遍代码岂不是很麻烦,尤其是出错时,Rollback需要多次在不同错误的地方的进行调用处理。

简单封装

偷懒第一步

采用defer处理Rollback

defer tx.Rollback()

无论成功与否,均进行Rollback操作,只是有点影响,如果成功还调用Rollback的话,将会报错。虽然可以忽略,但作为程序员,有必要进一步调整。

偷懒第二步

根据执行结果来选择执行Rollback,避免无效使用。

defer func() { //根据执行结果选择执行Rollback
        if err != nil && tx != nil {
        log.Println("ExecSqlWithTransaction defer err :", err)
            tx.Rollback()
        }
    }()

如此,我们就可以根据事务的执行结果决定是否Rollback了。

偷懒第三步

封装,以上代码本身就具有极大的普适性,因此,我们抽出通用的参数,将此过程封装成一个func,以后就可以直接调用了。

func ExecSqlWithTransaction(database *sql.DB, query string, args ...interface{}) (err error) {
    tx, err := database.Begin()
    if err != nil {
        return err
    }
    defer func() {
        if err != nil && tx != nil {
            tx.Rollback()
        }
    }()
    stmt, err := tx.Prepare(query)
    if err != nil {
        return err
    }
    defer stmt.Close()
    _, err = stmt.Exec(args...)
    if err != nil {
        return err
    }
    return tx.Commit()
}

封装后我们可以如下使用:

if err := ExecSqlWithTransaction(database,sqlQuery,paras...);err != nil{
    //错误处理
}

封装后是不是很简洁啊?

进一步封装

在一个事务中可能会出现多个SELECT、UPDATE等操作,以上封装仅处理了一种操作,还不能满足我们的实际需求,因此需要更进一步封装。

func ExecSqlWithTransaction(db *sql.DB, handle func(tx *sql.Tx) error) (err error) {
 tx, err := db.Begin()
 if err != nil {
  return err
 }
 defer func() {
  if err != nil {
   tx.Rollback()
  }
 }()
 if err = handle(tx); err != nil {
  return err
 }
 return tx.Commit()
}

在handle func内可以直接使用事务tx进行增删改查。

到此这篇关于golang db事务的统一封装的实现的文章就介绍到这了,更多相关golang db事务封装内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
  • golang配制高性能sql.DB的使用
  • Golang Mongodb模糊查询的使用示例
  • mongodb官方的golang驱动基础使用教程分享
  • golang 连接mongoDB的方法示例
  • Golang对MongoDB数据库的操作简单封装教程

相关文章

  • golang?db事务的统一封装的实现

    golang?db事务的统一封装的实现

    目录简单封装偷懒第一步 偷懒第二步 偷懒第三步 进一步封装事务处理的流程示例 database := db.DB tx, err := database.Beg
    2022-01-27
  • 浅谈Gin框架中bind的使用

    浅谈Gin框架中bind的使用

    目录概述Binding接口context.Bindcnotext.MustBindWithShouldBindWithcontext.BindJSONcontext.ShouldBindJSONcontext.ShouldBindUri()conte
    2022-01-27
  • Go并发编程中sync/errGroup的使用

    Go并发编程中sync/errGroup的使用

    目录一.序二.errGroup2.1 函数签名 三.源码3.1 Group 3.2 WaitContext 3.3 Go 3.4 Wait 四. 案例五. 参考一.序 这一篇算是并发编程的
    2022-01-27
  • Go语言原子操作及互斥锁的区别

    Go语言原子操作及互斥锁的区别

    目录增或减比较并交换(Compare And Swap)载入与存储交换原子值原子操作与互斥锁的区别原子操作就是不可中断的操作,外界是看不到原子操作的
    2022-01-27
  • Go语言并发爬虫的具体实现

    Go语言并发爬虫的具体实现

    目录写在前面1. 单线程爬虫2. 多线程爬虫2.1 channel main函数2.2 sync.WaitGroup3. 源码地址写在前面 这篇文章主要让大家明白多线程爬虫,
    2022-01-27
  • Go?container包的介绍

    Go?container包的介绍

    目录1.简介2.list2.1数据结构 2.2插入元素3.ring3.1数据结构 4.heap4.1数据结构 1.简介 Container — 容器数据类型:该包实现了三个复
    2022-01-27
  • Go语言做爬虫状态码返回418的问题解决

    Go语言做爬虫状态码返回418的问题解决

    目录背景原因分析代码部分背景 ?在使用Go语言做爬虫时,使用http.Get(url)去获取网页内容,状态码返回404,Body体为空。 原因分析 ?http
    2022-01-27
  • golang实现数组分割的示例代码

    golang实现数组分割的示例代码

    需求:给定一个数组和一个正整数,要求把数组分割成多个正整数大小的数组,如果不够分,则最后一个数组分到剩余的所有元素。 示例1:
    2022-01-27
  • Go语言参数传递是传值还是传引用

    Go语言参数传递是传值还是传引用

    目录什么是传值(值传递)什么是传引用(引用传递)迷惑Mapchan类型和map、chan都不一样的slice小结对于了解一门语言来说,会关心我们在函数调
    2022-01-27
  • vscode搭建go开发环境案例详解

    vscode搭建go开发环境案例详解

    目录前言一、安装goLang二.配置环境变量三、vscode安装插件四.安装golang依赖五.新建go文件提示:文章写完后,目录可以自动生成,如何生成可
    2022-01-27

最新评论