精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Go工程化如何在整潔架構中使用事務?

開發 后端
事務的能力是在 repo 上提供的,所以我們需要在 repo 層提供一個事務接口,然后在 usecase 中進行調用,保證是事務執行的就行。

[[441824]]

回顧先簡單回顧一下 《Go工程化(九) 項目重構實踐》 如果還沒看過之前這篇文章可以先看一下:

在我們之前的項目目錄分層中,我們主要分為了五個塊:

  • cmd/appname 是我們服務的入口,只負責啟動和依賴注入(使用 Wire)
  • domain 或者 model 是我們的實體定義 + 接口定義
  • server 負責實現我們在 proto 中定義的接口,在這一層中我們只做數據轉換,不寫業務邏輯
  • usecase 負責實現我們的業務邏輯
  • repo 負責數據操作, 僅做數據操作,不實現業務邏輯

在之前的文章中僅僅提到了一個非常簡單的示例,但是我們實際業務流程往往沒有那么簡單,就一個非常常見的例子,我們現在需要創建一篇文章,文章上需要關聯分類或者是標簽信息,這里至少就分兩步:

  • 創建文章
  • 關聯文章和標簽

這兩個創建操作需要保證一致性,我們需要在數據庫中使用事務,這時候我們的事務在哪里承載呢?

在 repo 層承載事務

其中最簡單也最直接的辦法就是在 repo 的 CreateArticle 方法中我們就使用事務去同時創建文章以及標簽之間的關聯關系。

  • 我們不是所有的業務場景都需要關聯創建,有的場景下我們只需要一個單純的方法又怎么辦呢?
  • 這么寫還有一個問題,我們把業務邏輯下沉到了 repo 中,后面我們還有其它關聯也這么搞么?

針對第一個問題,最簡單的辦法就是我們提供一個 CreateArticleWithTags 方法表示同時創建這兩者,如果我們需要一個獨立的 CreateArticle 再寫一個就好了。

但是隨著需求越來越多,可能后面還有需要和角色關聯的,和商品關聯的等等。

難道我們就一種邏輯寫一個方法么。想想就可怕。

還是在參數中加上很多可選的 options,然后在一個方法中不斷判斷。那我們還拿 usecase 做什么直接寫一起不更好么?

在 usecase 層承載事務

ok,所以直接在 repo 層里面來實現看上去好像行不通,那我們就把視線往上移動,我們在 usecase 來解決這個問題。

事務的能力是在 repo 上提供的,所以我們需要在 repo 層提供一個事務接口,然后在 usecase 中進行調用,保證是事務執行的就行。

使用 repo 層提供的事務接口

  1. // domain/article.go 
  2. // ArticleRepoTxFunc 事務方法 
  3. type ArticleRepoTxFunc = func(ctx context.Context, repo IArticleRepo) error 
  4. // IArticleRepo IArticleRepo 
  5. type IArticleRepo interface { 
  6.  Tx(ctx context.Context, f ArticleRepoTxFunc) error 
  7.  GetArticle(ctx context.Context, id int) (*Article, error) 
  8.  CreateArticle(ctx context.Context, article *Article) error 

在 repo 中,我們可以像上面這樣定義,提供一個 Tx 方法,這個方法接受一個 ArticleRepoTxFunc 作為參數,這個函數中的 repo 是開啟了事務的 repo,通過這個 repo 調用的所有方法都是在事務中執行的。

  1. // repo/article.go 
  2. func (r *article) Tx(ctx context.Context, f domain.ArticleRepoTxFunc) error { 
  3.  // 注意,這里的 r.db 是 *gorm.DB 
  4.   // 在 gorm 中提供了 Transaction 的工具方法用于執行事務,這里我們就不自己寫了 
  5.  return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { 
  6.   // 我們使用事務的 tx 重新初始化一個 repo 
  7.     // 這個 repo 后續的執行的數據庫相關的操作就都是事務的了 
  8.   repo := NewArticleRepo(tx) 
  9.   return f(ctx, repo) 
  10.  }) 

然后我們在 usecase 調用的時候就可以這樣。

  1. // usecase/article.go 
  2. func (u *article) CreateArticle(ctx context.Context, article *domain.Article, tagIDs []uint) error { 
  3.  return u.repo.Tx(ctx, func(ctx context.Context, repo domain.IArticleRepo) error { 
  4.   err := repo.CreateArticle(ctx, article) 
  5.   if err != nil { 
  6.    return err 
  7.   } 
  8.   var ats []*domain.ArticleTag 
  9.   for _, tid := range tagIDs { 
  10.    ats = append(ats, &domain.ArticleTag{ 
  11.     ArticleID: article.ID, 
  12.     TagID:     tid, 
  13.    }) 
  14.   } 
  15.   return repo.CreateArticleTags(ctx, ats) 
  16.  }) 

這樣寫起來就整潔很多了,業務邏輯和我們最初的設計一樣,在 usecase 中實現了,repo 中我們也保持了簡單的原則。

這樣是不是就萬事大吉了呢?如果萬事大吉了這篇文章到這兒也就應該結束了,但是還沒有,說明我在實踐的過程中還碰到了問題。

問題很簡單,就是我們在 usecase 中不僅僅需要復用 repo 中的代碼,還有可能需要復用 usecase 中的代碼,不然我們就可能在 usecase 中出現很多相同的邏輯代碼片段,代碼的重復率就很高。

我們來看下面一個例子會不會發現有點什么不對。

  1. // usecase/article.go 
  2. func (u *article) A(ctx contect, args args) error { 
  3.  err := u.CreateArticle(ctx, args.Article) // 包含事務 
  4.   if err != nil { 
  5.     return err 
  6.   } 
  7.   return u.UpdateXXX(ctx, args.XXX) // 這個方法中也使用了事務 

這個方法內其實是開啟了兩個事務,這兩個事務之間互不相關,不符合我們需求。

在 usecase 層提供事務方法

  1. // usecase/article.go 
  2. type handler func(ctx context.Context, usecase domain.IArticleUsecase) error 
  3. func (u *article) tx(ctx context.Context, f handler) error { 
  4.  return u.repo.Tx(ctx, func(ctx context.Context, repo domain.IArticleRepo) error { 
  5.   usecase := NewArticleUsecase(repo) 
  6.   return f(ctx, usecase) 
  7.  }) 

我們在 usecase 中也創建了一個 tx 方法,和 repo 類似,在調用 tx 之后,handler 中的方法的需要都是用新的參數 usecase 這個新的 usecase 可以保證里面的 repo 調用都是事務的。

所以我們之前的 A 函數可以修改為這樣:

  1. // usecase/article.go 
  2. func (u *article) A(ctx contect, args args) error { 
  3.  return u.tx(ctx, func(ctx context.Context, usecase domain.IArticleUsecase) error { 
  4.   err := usecase.CreateArticle(ctx, args.Article) // 包含事務 
  5.    if err != nil { 
  6.      return err 
  7.    } 
  8.    return usecase.UpdateXXX(ctx, args.XXX) // 這個方法中也使用了事務 
  9.  }) 

這樣就沒有問題了么?我們 UpdateXXX 方法中也調用 u.tx 方法,這樣就會導致反復開啟事務,雖然在 gorm 的 Transaction 方法是支持嵌套事務的,但是我們還是不要濫用這個特性。

解決辦法很簡單,我們只需要在執行的時候判斷下就行了。

  1. // usecase/article.go 
  2. type article struct { 
  3.  repo domain.IArticleRepo 
  4.   isTx bool // 用于標識是否開啟了事務 

然后我們在 tx 方法內:

  1. func (u *article) tx(ctx context.Context, f handler) error { 
  2.   // 如果已經開啟過事務了我們就直接復用就行了 
  3.  if u.isTx { 
  4.   return f(ctx, u) 
  5.  } 
  6.  return u.repo.Tx(ctx, func(ctx context.Context, repo domain.IArticleRepo) error { 
  7.   usecase := &article{ 
  8.    repo: repo, 
  9.    isTx: true
  10.   } 
  11.   return f(ctx, usecase) 
  12.  }) 

總結

文章到這里就到尾聲了,同樣的問題,我們現在這么寫就可以了么?

對于我當前所遇到的一些需求來說已經可以解決了,當然這個方案并不完美,比如說我們涉及到多個 repo 的時候,當前的方法就沒法直接用了,還得進行一些改造,雖然我們要有遠見但是也不要想的太多,進化是優于完美的。

 

責任編輯:姜華 來源: mohuishou
相關推薦

2021-03-19 07:23:23

Go架構Go工程化

2023-06-28 08:25:14

事務SQL語句

2021-12-27 08:27:18

RepoGo 代碼

2022-04-18 09:41:14

Go架構設計

2023-09-15 10:33:45

前端工程化commit

2016-02-22 15:02:57

GoRedis連接池

2024-01-18 08:37:33

socketasyncio線程

2022-06-23 08:00:53

PythonDateTime模塊

2021-06-09 09:36:18

DjangoElasticSearLinux

2021-03-09 07:27:40

Kafka開源分布式

2011-08-10 09:31:41

Hibernateunion

2015-08-27 09:46:09

swiftAFNetworkin

2022-05-17 08:25:10

TypeScript接口前端

2019-09-16 19:00:48

Linux變量

2014-07-02 09:47:06

SwiftCocoaPods

2020-11-30 11:55:07

Docker命令Linux

2020-04-09 10:18:51

Bash循環Linux

2024-09-06 11:34:15

RustAI語言

2019-10-11 10:44:30

Go語言數據庫軟件

2023-04-07 11:05:53

點贊
收藏

51CTO技術棧公眾號

国产情侣呻吟对白高潮| 午夜国产一区二区三区| 亚洲第一黄色片| 亚洲精品影院在线观看| 亚洲毛茸茸少妇高潮呻吟| 国产精品第12页| caoporn免费在线视频| 成人免费毛片a| 国产精品99免视看9| 国产真实乱在线更新| 美女午夜精品| 香蕉久久夜色精品| 综合久久五月天| 欧美一级片在线免费观看| 欧美丰满熟妇bbbbbb百度| 免费在线观看黄视频| 一本色道久久综合狠狠躁的番外| 欧美日韩综合不卡| 久久久精彩视频| 一级黄色短视频| 国产日韩欧美一区在线 | 在线观看亚洲黄色| 欧美午夜影院| 日韩中文字幕免费视频| 91视频啊啊啊| caoporn成人免费视频在线| 欧美日韩在线电影| 可以在线看的黄色网址| missav|免费高清av在线看| 国产精品久久久久久久第一福利| 精品久久sese| 亚洲精品久久久久久动漫器材一区| 青青草97国产精品免费观看| 久久久久久久久久国产精品| 情侣偷拍对白清晰饥渴难耐| 欧美猛男男男激情videos| 亚洲成人免费在线视频| 伊人影院在线观看视频| 亚洲欧美在线综合| 欧美在线视频不卡| 日本999视频| 欧美特大特白屁股xxxx| 婷婷久久综合| 国产日韩欧美不卡在线| 91久色国产| 国产精品国产三级国产aⅴ| 肉肉av福利一精品导航| 欧美成人高清电影在线| 欧洲精品视频在线| 麻豆视频在线免费观看| 国产女人aaa级久久久级| 欧美日韩喷水| 国产尤物视频在线观看| 日韩国产精品91| 国产99久久精品一区二区| 最新日韩免费视频| 国产精品xnxxcom| 欧美精品在线一区二区三区| 手机免费av片| 青草影视电视剧免费播放在线观看| 国产成人av一区二区三区在线观看| 国模私拍视频一区| 日本熟妇成熟毛茸茸| 在线亚洲国产精品网站| 欧美在线欧美在线| 久久精品国产亚洲av麻豆蜜芽| 日精品一区二区三区| 国产精品视频网址| 国产视频一二三四区| 久久aimee| 亚洲欧美久久久| 日韩中文综合网| 东方av正在进入| 乱亲女h秽乱长久久久| 亚洲国产成人精品电影| 国产又黄又粗又猛又爽的视频| 思热99re视热频这里只精品| 欧美电影一区二区| 男插女视频网站| 久久a爱视频| 亚洲性生活视频在线观看| 波兰性xxxxx极品hd| 午夜日韩激情| 欧美一级视频在线观看| 亚洲熟妇av乱码在线观看| 国产精品2024| 精品国产乱码久久久久| youjizz在线播放| 成人激情动漫在线观看| 九九九热999| 国产日产一区二区三区| 精品国产福利视频| 亚洲综合av在线播放| 国产精品中文字幕制服诱惑| 亚洲最大中文字幕| 亚洲熟女www一区二区三区| 亚洲自啪免费| 91精品国产99久久久久久红楼| 天堂在线中文资源| 亚洲欧洲日产国产综合网| 欧美日韩国产高清视频| 欧美极品另类| 天天影视涩香欲综合网| 少妇一级淫免费放| 精品网站aaa| www.精品av.com| 日韩电影在线观看一区二区| 高清不卡一区二区| 亚洲欧美日韩另类精品一区二区三区 | 欧美人xxxxx| 国产人成网在线播放va免费| 日韩欧美高清在线视频| 韩国三级hd中文字幕有哪些| 国产一区二区三区日韩精品| 午夜精品久久久久久久久久久久| 一本色道久久综合无码人妻| 91视频com| 波多野结衣av一区二区全免费观看| 成人国产精品入口免费视频| 亚洲精品国产精品国自产在线| 久久久精品少妇| 日韩va欧美va亚洲va久久| 粉嫩高清一区二区三区精品视频 | 亚洲视频在线一区二区| 欧美 日韩 国产 激情| 久久男人av| 欧美精品aaa| 国产精品久久久久久久免费 | 亚洲精品日韩精品| 婷婷午夜社区一区| 日韩hd视频在线观看| 国产麻豆剧传媒精品国产av| 国产精品成人a在线观看| 国产91免费看片| 欧美拍拍视频| 日韩欧美视频一区二区三区| 尤物网站在线观看| 亚洲成人原创| 精品国产一区二区三区四区精华 | 色欲久久久天天天综合网| 亚洲激情自拍偷拍| 自拍一级黄色片| 亚洲国产精品91| 亚洲va电影大全| 在线中文字幕第一页| 正在播放亚洲一区| 国产又黄又爽又无遮挡| 国产一区二区91| 欧美做受777cos| 色妞ww精品视频7777| 亚洲黄页视频免费观看| 国产亚洲精品女人久久久久久| 国产高清一区在线观看| 国产激情精品久久久第一区二区 | 免费无码一区二区三区| 亚洲精品乱码| 欧美三日本三级少妇三99| 松下纱荣子在线观看| 日韩精品中文字| 亚洲av无码精品一区二区| 国产色婷婷亚洲99精品小说| 超碰在线97免费| 我不卡影院28| 成人免费看片网址| 精精国产xxxx视频在线播放| 精品无码久久久久久国产| 亚洲精品中文字幕乱码三区91| 久久久久久久久久久久久久久99| 亚洲精美视频| av在线国产精品| 欧美激情国产高清| 手机看片福利在线| 在线视频你懂得一区| 制服丨自拍丨欧美丨动漫丨| 精久久久久久久久久久| 日韩视频 中文字幕| 奇米777国产一区国产二区| 国产精品爱久久久久久久| 日本韩国在线视频爽| 日韩精品一区二区三区四区| 男人的天堂一区二区| 国产亲近乱来精品视频| 国产亚洲色婷婷久久| 国产日韩一区二区三区在线播放| 日韩精品最新在线观看| 欧美黄视频在线观看| 91成人国产在线观看| 色多多视频在线观看| 日韩精品专区在线影院重磅| 永久免费无码av网站在线观看| 中文字幕在线不卡国产视频| 免费看毛片的网站| 精品在线播放免费| 18禁男女爽爽爽午夜网站免费 | 99久久久精品视频| 蜜臀av免费一区二区三区| 成人夜晚看av| 日本三级一区| 美女扒开尿口让男人操亚洲视频网站| 天堂av资源网| 这里只有精品免费| 国产一级精品视频| 国产精品主播直播| 国产 福利 在线| 99久久精品国产亚洲精品| 久久大香伊蕉在人线观看热2| 欧美日韩卡一| 热草久综合在线| 少女频道在线观看高清 | 日韩av男人的天堂| freemovies性欧美| 亚洲成人av片在线观看| 中文字幕在线观看免费| 五月天一区二区三区| 日本黄色免费片| 国产色产综合色产在线视频 | 久久综合久久鬼色中文字| 婷婷激情小说网| 大色综合视频网站在线播放| 国产98在线|日韩| 免费视频成人| 国产成人av在线播放| 国产资源在线观看入口av| 久热精品视频在线免费观看| 国产在线视频福利| 亚洲精品国产免费| 午夜精品久久久久久久99热黄桃 | 五月婷婷激情网| 一区二区在线看| 久久国产高清视频| 国产精品久久久久久妇女6080| 中文字幕一区二区三区人妻不卡| 成人午夜视频福利| 国产伦精品一区二区三区妓女下载| 蜜乳av一区二区| 天天综合五月天| 久久在线电影| 亚洲欧美国产精品桃花| 成人一区而且| 8x8x8国产精品| 99999精品视频| 亚洲黄色精品| 免费人成自慰网站| 林ゆな中文字幕一区二区| 成人在线小视频| 中文成人在线| 91在线观看免费| 精品视频在线观看免费观看| 亚洲淫片在线视频| 日韩欧美另类中文字幕| 99精品在线直播| 91av亚洲| 日本成熟性欧美| 国产高清不卡| 国产99久久精品一区二区 夜夜躁日日躁 | 欧美韩日一区二区三区四区| 亚洲精品午夜视频| 韩国视频一区二区| 91精品999| 国产酒店精品激情| 国产高潮视频在线观看| 不卡的av网站| 国精产品一区一区三区免费视频 | 久久久国产成人| 五月激情综合婷婷| 在线观看免费av片| 亚洲三级免费电影| www青青草原| 亚洲电影第三页| 国产wwwwxxxx| 亚洲欧美一区二区三区孕妇| 欧美一级久久久久久久大片| 国产成人在线免费观看视频| 狠狠久久五月精品中文字幕| 99re国产在线| 69久久99精品久久久久婷婷| 成人福利小视频| 国产视频久久网| 在线视频婷婷| 国内精品在线一区| 9i看片成人免费高清| 国产九九精品视频| 欧美人体一区二区三区| 国产精品视频xxxx| 91精品啪在线观看国产爱臀| 久久久久久亚洲精品不卡4k岛国 | 亚洲高潮无码久久| 亚洲美女毛片| 伊人色在线观看| 99久久久无码国产精品| 午夜国产福利视频| 粉嫩av一区二区三区免费野| 亚洲影院一区二区三区| 精品久久久久一区| av中文资源在线| 国内免费久久久久久久久久久| 成人国产在线| 精品国产免费久久久久久尖叫 | 超碰成人免费在线| 免费欧美在线视频| 熟妇人妻久久中文字幕| 国产精品国产自产拍高清av王其| 日本天堂在线视频| 91精品国产日韩91久久久久久| 婷婷亚洲一区二区三区| 欧美成人免费视频| 国产私拍福利精品视频二区| 一区二区三区四区不卡在线| 国产精品天天av精麻传媒| 国产毛片精品国产一区二区三区| 国产精品亚洲无码| 亚洲一区自拍偷拍| 国产女人18毛片18精品| 亚洲天堂男人天堂女人天堂| 免费影视亚洲| 亚洲va电影大全| 国产精品伦理久久久久久| 亚洲爆乳无码专区| 成人黄色大片在线观看| 欧美黄色aaa| 欧美日韩成人综合在线一区二区| 欧美另类自拍| 97av在线播放| 成人知道污网站| 欧美极品少妇无套实战| 久久99精品国产| jizz日本在线播放| 色8久久精品久久久久久蜜| 黄色片视频网站| 日韩区在线观看| 顶级网黄在线播放| 国产日韩精品一区二区| 国产欧美日韩影院| 久久久久免费精品| 26uuu亚洲综合色欧美| 日韩特黄一级片| 欧美久久久久久久久久| 黄在线免费观看| 成人精品久久久| 久久久久久久久丰满| 亚洲欧美手机在线| 亚洲天堂av老司机| 国产乱子伦精品无码码专区| 久久精品亚洲热| 国产精品美女久久久久人| 国产又粗又爽又黄的视频| 激情综合亚洲精品| 91杏吧porn蝌蚪| 日韩视频免费观看高清完整版在线观看| 毛片网站在线免费观看| 成人写真视频福利网| 欧美成人综合| 永久免费黄色片| 亚洲精品国产品国语在线app| 亚洲国产精品欧美久久| 欧美国产日本高清在线| 欧美夫妇交换xxx| 亚洲午夜激情av| 色噜噜一区二区三区| 97人人做人人爱| 伊人久久大香线蕉综合网蜜芽| 国产熟女高潮视频| 国产精品丝袜在线| 国产色综合视频| 国内精品久久久久久影视8| 欧美日韩精品一区二区三区在线观看| 97超碰国产精品| 26uuu精品一区二区三区四区在线| www.国产毛片| 久久色精品视频| 国产精品极品| 国产v亚洲v天堂无码久久久 | 精品无人区卡一卡二卡三乱码免费卡| www深夜成人a√在线| 日韩美女视频在线| 亚洲午夜天堂| 日韩欧美在线一区二区| 国产一区啦啦啦在线观看| 国产系列精品av| 国产一区二区三区在线观看视频 | 少妇aaaaa| 亚洲韩国欧洲国产日产av| 欧美123区| 大西瓜av在线| 国产欧美日韩另类视频免费观看 | 日韩精品中文字幕有码专区| 成人开心激情| 国产欧美久久久久| 国产日韩欧美制服另类| av网站在线免费看| 日本久久91av| 欧美久久综合| 美国美女黄色片| 亚洲福利视频专区| 午夜精品久久久久久毛片| 国产一区二区网| 亚洲欧洲精品一区二区精品久久久 | 国产精品1区二区.| 伊人久久久久久久久久久久| 色综合色综合久久综合频道88|