• 基于gin的golang web开发:使用数据库事务


    在前文介绍访问数据库时介绍了github.com/jmoiron/sqlx包,本文基于这个包使用数据库事务。

    defer

    在使用数据库事务之前,首先需要了解go语言的defer关键字。defer是go语言的延迟执行语句,defer后面的语句会被go进行延迟处理,在函数即将结束的时候,defer后面的语句将逆序执行。也就是说,先defer的语句最后执行。defer很像java或者C#中的finally语句。下面通过一个例子看一下defer。

    package main
    
    import "fmt"
    
    func main() {
    	fmt.Println("defer 开始")
    	defer fmt.Println(1)
    	defer fmt.Println(2)
    	defer fmt.Println(3)
    	panic("测试 panic")
    	fmt.Println("defer 结束")
    }
    

    代码运行结果:

    defer 开始
    3
    2
    1
    panic: 测试 panic
    
    goroutine 1 [running]:
    main.main()
    	/tests/gookokok/main.go:10 +0x1b8
    
    Process finished with exit code 2
    

    通过运行结果可以看到defer的逆序输出。在之后又手动触发了一个panic,影响了最后一行的输出defer 结束,go在触发panic时优先执行了defer,足以证明defer是非常安全的,所以defer也常常被用来互斥解锁、关闭文件或数据库事务的处理。

    事务

    sqlx使用事务和database/sql相比扩展出了MustBegin()、MustExec()等方法,这样就不需要在代码中手动处理很多错误。MustBegin会在出现错误的时候触发panic而不是返回错误,这样就可以在代码的更上一层统一处理错误。

    tx, err := db.Begin()
    err = tx.Exec(...)
    err = tx.Commit()
    
    tx := db.MustBegin()
    tx.MustExec(...)
    err = tx.Commit()
    

    sqlx支持以上两种开启事务的方法。MustBegin返回sqlx.Tx,sqlx.Tx也提供了Select,Get之类的API,执行数据库操作和使用sqlx.DB是一样的。

    以上代码执行tx.MustExec(...)如果报错的话,代码将没有机会运行到tx.Commit(),这样数据库连接会等到go进行垃圾回收的时候才能关闭,而且很高并发的话,可能会占满数据库连接数,造成站点无法访问的情况。

    tx := db.MustBegin()
    defer tx.Rollback()
    tx.MustExec(...)
    err = tx.Commit()
    

    代码中加入defer tx.Rollback()就可以解决问题。通过前面的介绍已知defer是在方法即将结束时执行,哪怕是代码出现异常也不会影响数据库连接。

    文章出处:基于gin的golang web开发:使用数据库事务

  • 相关阅读:
    下载windows原装镜像的官方网站
    Typora快捷键
    UOS使用ZSH终端教程
    UOS每日折腾、调教、美化
    AMD64和X86_64
    CPU架构
    23种设计模式---单例设计模式(精华)
    java学习day32-Servlet上下文--ServletContext
    java学习day32-Servlet过滤器-Filter
    java学习day32-JSP标签技术-JSTL标签库
  • 原文地址:https://www.cnblogs.com/huaface/p/13958267.html
Copyright © 2020-2023  润新知