本文中作者展示了golang事務(wù)的三種寫法。
第一種寫法
這種寫法非常樸實,程序流程也非常明確,但是事務(wù)處理與程序流程嵌入太深,容易遺漏,造成嚴(yán)重的問題
funcDoSomething()(errerror){
tx,err:=db.Begin()
iferr!=nil{
return
}
deferfunc(){
ifp:=recover();p!=nil{
tx.Rollback()
panic(p)//re-throwpanicafterRollback
}
}()
if_,err=tx.Exec(...);err!=nil{
tx.Rollback()
return
}
if_,err=tx.Exec(...);err!=nil{
tx.Rollback()
return
}
//...
err=tx.Commit()
return
}
第二種寫法
下面這種寫法把事務(wù)處理從程序流程抽離了出來,不容易遺漏,但是作用域是整個函數(shù),程序流程不是很清晰
funcDoSomething()(errerror){
tx,err:=db.Begin()
iferr!=nil{
return
}
deferfunc(){
ifp:=recover();p!=nil{
tx.Rollback()
panic(p)//re-throwpanicafterRollback
}elseiferr!=nil{
tx.Rollback()
}else{
err=tx.Commit()
}
}()
if_,err=tx.Exec(...);err!=nil{
return
}
if_,err=tx.Exec(...);err!=nil{
return
}
//...
return
}
第三種寫法
寫法三是對寫法二的進一步封裝,寫法高級一點,缺點同上
funcTransact(db*sql.DB,txFuncfunc(*sql.Tx)error)(errerror){
tx,err:=db.Begin()
iferr!=nil{
return
}
deferfunc(){
ifp:=recover();p!=nil{
tx.Rollback()
panic(p)//re-throwpanicafterRollback
}elseiferr!=nil{
tx.Rollback()
}else{
err=tx.Commit()
}
}()
err=txFunc(tx)
returnerr
}
funcDoSomething()error{
returnTransact(db,func(tx*sql.Tx)error{
if_,err:=tx.Exec(...);err!=nil{
returnerr
}
if_,err:=tx.Exec(...);err!=nil{
returnerr
}
})
}
我的寫法
經(jīng)過總結(jié)和實驗,我采用了下面這種寫法,defer tx.Rollback() 使得事務(wù)回滾始終得到執(zhí)行。當(dāng) tx.Commit() 執(zhí)行后,tx.Rollback() 起到關(guān)閉事務(wù)的作用, 當(dāng)程序因為某個錯誤中止,tx.Rollback() 起到回滾事務(wù),同事關(guān)閉事務(wù)的作用。
普通場景
funcDoSomething()(errerror){
tx,_:=db.Begin()
defertx.Rollback()
if_,err=tx.Exec(...);err!=nil{
return
}
if_,err=tx.Exec(...);err!=nil{
return
}
//...
err=tx.Commit()
return
}
循環(huán)場景
(1) 小事務(wù) 每次循環(huán)提交一次 在循環(huán)內(nèi)部使用這種寫法的時候,defer 不能使用,所以要把事務(wù)部分抽離到獨立的函數(shù)當(dāng)中
funcDoSomething()(errerror){
tx,_:=db.Begin()
defertx.Rollback()
if_,err=tx.Exec(...);err!=nil{
return
}
if_,err=tx.Exec(...);err!=nil{
return
}
//...
err=tx.Commit()
return
}
for{
iferr:=DoSomething();err!=nil{
//...
}
}
(2) 大事務(wù) 批量提交 大事務(wù)的場景和普通場景是一樣的,沒有任何區(qū)別
funcDoSomething()(errerror){
tx,_:=db.Begin()
defertx.Rollback()
for{
if_,err=tx.Exec(...);err!=nil{
return
}
if_,err=tx.Exec(...);err!=nil{
return
}
//...
}
err=tx.Commit()
return
}
原文標(biāo)題:Golang transaction 事務(wù)使用的正確姿勢
文章出處:【微信公眾號:馬哥Linux運維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
審核編輯:湯梓紅
-
封裝
+關(guān)注
關(guān)注
128文章
8598瀏覽量
145001 -
程序
+關(guān)注
關(guān)注
117文章
3825瀏覽量
82586 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4374瀏覽量
64423
原文標(biāo)題:Golang transaction 事務(wù)使用的正確姿勢
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
【科普】三種電磁屏蔽的目的及原理詳解

TCPIP詳解卷三:TCP事務(wù)協(xié)議,HTTP,NNTP和UNIX域協(xié)議
常見三種接口詳解
STM32的三種boot模式介紹
三種投影機散熱技術(shù)是哪三種
三種不同的“防 Ping”技巧
淺析單片機三種應(yīng)用程序的架構(gòu)
PCB常見的三種鉆孔詳解資料下載

MySQL三種日志講解

評論