Golang transaction 事务使用的正确姿势

本文中作者展示了 golang 事务的正确姿势三种写法。
第一种写法
这种写法非常朴实,正确姿势程序流程也非常明确,正确姿势但是正确姿势事务处理与程序流程嵌入太深,容易遗漏,正确姿势造成严重的正确姿势问题
func DoSomething() (err error) {
tx, err := db.Begin()
if err != nil {
return
}
defer func() {
if p := recover(); p != nil {
tx.Rollback()
panic(p) // re-throw panic after Rollback
}
}()
if _, err = tx.Exec(...); err != nil {
tx.Rollback()
return
}
if _, err = tx.Exec(...); err != nil {
tx.Rollback()
return
}
// ...
err = tx.Commit()
return
}
第二种写法
下面这种写法把事务处理从程序流程抽离了出来,不容易遗漏,正确姿势但是正确姿势作用域是整个函数,云服务器程序流程不是正确姿势很清晰
func DoSomething() (err error) {
tx, err := db.Begin()
if err != nil {
return
}
defer func() {
if p := recover(); p != nil {
tx.Rollback()
panic(p) // re-throw panic after Rollback
} else if err != nil {
tx.Rollback()
} else {
err = tx.Commit()
}
}()
if _, err = tx.Exec(...); err != nil {
return
}
if _, err = tx.Exec(...); err != nil {
return
}
// ...
return
}
第三种写法
写法三是对写法二的进一步封装,写法高级一点,正确姿势缺点同上
func Transact(db *sql.DB,正确姿势 txFunc func(*sql.Tx) error) (err error) {
tx, err := db.Begin()
if err != nil {
return
}
defer func() {
if p := recover(); p != nil {
tx.Rollback()
panic(p) // re-throw panic after Rollback
} else if err != nil {
tx.Rollback()
} else {
err = tx.Commit()
}
}()
err = txFunc(tx)
return err
}
func DoSomething() error {
return Transact(db, func (tx *sql.Tx) error {
if _, err := tx.Exec(...); err != nil {
return err
}
if _, err := tx.Exec(...); err != nil {
return err
}
})
}
我的写法
经过总结和实验,我采用了下面这种写法,正确姿势defer tx.Rollback() 使得事务回滚始终得到执行。正确姿势当 tx.Commit() 执行后,正确姿势tx.Rollback() 起到关闭事务的正确姿势作用,香港云服务器 当程序因为某个错误中止,tx.Rollback() 起到回滚事务,同事关闭事务的作用。
普通场景
func DoSomething() (err error) {
tx, _ := db.Begin()
defer tx.Rollback()
if _, err = tx.Exec(...); err != nil {
return
}
if _, err = tx.Exec(...); err != nil {
return
}
// ...
err = tx.Commit()
return
}
循环场景
(1) 小事务 每次循环提交一次 在循环内部使用这种写法的时候,defer 不能使用,所以要把事务部分抽离到独立的函数当中
func DoSomething() (err error) {
tx, _ := db.Begin()
defer tx.Rollback()
if _, err = tx.Exec(...); err != nil {
return
}
if _, err = tx.Exec(...); err != nil {
return
}
// ...
err = tx.Commit()
return
}
for {
if err := DoSomething(); err != nil{
// ...
}
}
(2) 大事务 批量提交 大事务的场景和普通场景是一样的,服务器租用没有任何区别
func DoSomething() (err error) {
tx, _ := db.Begin()
defer tx.Rollback()
for{
if _, err = tx.Exec(...); err != nil {
return
}
if _, err = tx.Exec(...); err != nil {
return
}
// ...
}
err = tx.Commit()
return
}
相关文章
电脑主题安装密码错误的解决方法(忘记或输入错误密码时如何解决电脑主题安装问题)
摘要:在进行电脑主题安装过程中,有时候我们会遇到密码错误的问题。这可能是因为我们忘记了密码,或者是输入了错误的密码。无论是哪种情况,这都会导致我们无法正常地安装所需的电脑主题。为了帮助大...2025-11-05
使用 null 而不是传递一个空字符串,这可能会导致DOM输出中的一个空类。在你的三元操作符中,你可以返回 null。这将确保DOM中没有空类:<!--❌--><div:class=2025-11-05
作为新一轮科技革命与产业变革浪潮中的代表性技术,虚拟现实不仅能给人们的生产生活方式带来巨大影响,同时还能推动传统产业转型升级以及数字经济加速发展,其产业发展对于各国来说具有重要意义。历经几番沉浮,如今2025-11-05
前端小哥玩HTML复选框上瘾,能画logo做视频,还开源成JS库
本文经AI新媒体量子位公众号ID:QbitAI)授权转载,转载请联系出处。万万没想到,如此普通的复选框,竟也能玩出这种高度!例如点一下复选框,屏幕就像被投入石子的水面泛出波纹:设定好初始状态,就可以开2025-11-05解决电脑开机提示ID错误的方法(如何处理电脑开机时出现的ID错误提示信息)
摘要:电脑开机时出现ID错误提示信息是很常见的问题,很多用户都会遇到这个困扰。这种情况通常是由于操作系统或硬件故障引起的。在本文中,我们将详细介绍如何解决电脑开机提示ID错误的问题,帮助...2025-11-05
大家好,我是梁唐。这是EasyC++系列的第14篇,咱们来聊聊C++当中的枚举值。想要追求更好阅读体验的同学,可以点击文末的「阅读原文」,访问github仓库。枚举简介C++当中提供了枚举操作,我们可2025-11-05

最新评论