基于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是在方法即将结束时执行,哪怕是代码出现异常也不会影响数据库连接。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!