精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

中文字幕亚洲高清| 国产日韩成人内射视频| 国产三级三级在线观看| 国产理论在线观看| 国产一区二区久久| 91av国产在线| 色婷婷粉嫩av| 九热爱视频精品视频| 337p亚洲精品色噜噜噜| 日韩在线综合网| 欧美三级理伦电影| 91在线一区二区三区| 国产区亚洲区欧美区| 国产对白videos麻豆高潮| 欧美日韩性在线观看| 精品不卡在线视频| 一道本视频在线观看| 免费污视频在线| 国产精品青草综合久久久久99| 成人av免费看| 中文字幕一区二区三区波野结| 在线观看的日韩av| 日韩欧美一区二区免费| 那种视频在线观看| 国产盗摄一区二区| 亚洲三级理论片| 久久一区二区三区av| 99久久精品无免国产免费| 天堂精品中文字幕在线| 97色在线视频观看| 欧美三级免费看| 日韩免费看片| 一本色道久久88亚洲综合88| 日韩精品人妻中文字幕有码| 欧一区二区三区| 欧美视频网站| 精品一区二区三区蜜桃| 精品中文字幕在线2019| 少妇高潮在线观看| 清纯唯美综合亚洲| 国产一区二区三区久久精品| 国产乱子夫妻xx黑人xyx真爽 | 国产一区二区三区丝袜| 自拍视频一区二区| 久久毛片亚洲| 五月婷婷综合在线| 久艹视频在线免费观看| 美洲精品一卡2卡三卡4卡四卡| 中文字幕制服丝袜一区二区三区| 日韩高清国产精品| 国产伦精品一区二区三区视频痴汉 | 国产精品久久九九| 国产av无码专区亚洲av| 极品少妇xxxx偷拍精品少妇| 国产精品日日做人人爱| 国产精品无码一区| 一本精品一区二区三区| 社区色欧美激情 | 手机免费观看av| 国产精品99一区二区三区| 日韩在线视频一区| 国产美女福利视频| 欧美日韩爆操| 97久久久久久| 在线观看黄网站| 久久久久免费| 91精品久久久久久久久久| 国产日韩欧美一区二区东京热| 国产一区二三区| 国产精成人品localhost| 天天综合在线视频| 久久久国产精品午夜一区ai换脸| 色噜噜一区二区| 麻豆免费在线视频| 亚洲国产wwwccc36天堂| 欧美色图另类小说| 成人做爰免费视频免费看| www.我爱av| 麻豆成人久久精品二区三区小说| 91精品免费看| 人妻少妇精品无码专区| 久久久久久久电影| 中文精品一区二区三区| 精品欧美一区二区精品少妇| 福利91精品一区二区三区| 九九九九久久久久| 成人免费在线观看| 亚洲精品久久久蜜桃| 亚洲国产成人精品无码区99| 巨茎人妖videos另类| 欧美日韩亚洲国产综合| 精品人妻二区中文字幕| 四虎5151久久欧美毛片| www.亚洲人.com| 日操夜操天天操| 日本视频中文字幕一区二区三区| 亚洲在线www| 欧洲亚洲在线| 亚洲精品久久7777| 妞干网在线免费视频| aa亚洲一区一区三区| 日韩大陆毛片av| 看黄色录像一级片| 一区二区毛片| 国外色69视频在线观看| 成人免费毛片东京热| 一区二区三区成人精品| 国产欧美一区二区三区在线| 色欲av永久无码精品无码蜜桃| 亚洲国产精华液网站w| 按摩亚洲人久久| 成人黄色在线播放| 91在线看网站| 天天操天天舔天天射| 色婷婷一区二区三区| 韩国日本不卡在线| 又骚又黄的视频| 日韩二区在线观看| 国产精品青青草| 免费高清完整在线观看| 日韩欧美a级成人黄色| 中文字幕第10页| 国产亚洲一区| 亚洲最新视频在线| 国产成年人免费视频| 狠狠色丁香婷婷综合| 秋霞久久久久久一区二区| 丰满诱人av在线播放| 欧美精品一卡两卡| 九九九视频在线观看| 亚洲综合精品| 国产91亚洲精品一区二区三区| 毛片在线不卡| 欧美日韩在线一区二区| 色哟哟精品观看| 久久国产免费| 精品国产一区二区三区免费 | 国产aa精品| 一区二区三区视频在线| 国产高清中文字幕| av电影天堂一区二区在线观看| 欧美交换配乱吟粗大25p| 日韩综合久久| 日韩视频免费在线| 一级做a爰片久久毛片16| 国产精品少妇自拍| 少妇一级淫免费放| 色欧美自拍视频| 国产色婷婷国产综合在线理论片a| 加勒比一区二区三区在线| 欧美日韩精品国产| 国精产品一区一区三区免费视频| 国产精品乱看| 蜜桃精品久久久久久久免费影院| 日韩激情电影免费看| 日韩精品极品视频免费观看| 九一国产在线观看| 久久综合九色综合97婷婷女人| 奇米影视亚洲色图| 外国成人在线视频| 欧亚精品中文字幕| 中文字幕永久在线观看| 久久精品视频网| 91视频免费版污| 99久久精品网| 51成人做爰www免费看网站| 日本孕妇大胆孕交无码| 亚洲成人网在线观看| 久久精品www| 99久久综合精品| 国产成人精品无码播放| 91亚洲一区| 99久热re在线精品视频| 爱啪视频在线观看视频免费| 亚洲跨种族黑人xxx| 最近日韩免费视频| 亚洲欧美日韩一区二区三区在线观看| 少妇欧美激情一区二区三区| 亚洲理论在线| 中文字幕中文字幕在线一区| 国产精品av在线| 91亚洲国产成人久久精品麻豆| 国产精品国产精品国产专区不蜜| 宇都宫紫苑在线播放| 日韩五码在线| 色姑娘综合网| 亚洲欧美日本国产| 国产成人激情视频| 2024最新电影在线免费观看| 日韩av在线一区二区| 影音先锋国产资源| 亚洲大片一区二区三区| 免费看黄色av| 国产成人免费视频网站高清观看视频 | 久久亚洲在线| 国产综合av一区二区三区| 97欧美成人| 久久久亚洲网站| porn视频在线观看| 在线成人av观看| 亚洲欧洲美洲在线综合| 国产欧美熟妇另类久久久 | 免费一级特黄毛片| 欧美一区2区| 国产美女精品久久久| 国产69精品久久| 69av成年福利视频| а√天堂资源地址在线下载| 亚洲片国产一区一级在线观看| 国产探花精品一区二区| 色综合视频在线观看| 青娱乐在线视频免费观看| 国产日韩欧美a| av无码一区二区三区| 国产精品一级二级三级| 先锋影音亚洲资源| 久久久久观看| 91av在线国产| av免费在线观看网址| 亚洲午夜久久久影院| 国产18精品乱码免费看| 制服丝袜av成人在线看| 国产精品免费无遮挡无码永久视频| 久久综合资源网| 国模大尺度视频| 美女国产一区二区三区| 国内外成人免费激情视频| 精品动漫3d一区二区三区免费版| 亚洲最新免费视频| 国产成人一区| 蜜桃臀一区二区三区| 国产精品nxnn| 99久热re在线精品视频| 日本精品国产| 成人福利在线视频| a成人v在线| 国产精品视频免费在线| 粉嫩91精品久久久久久久99蜜桃 | 天天干天天色天天爽| 色狮一区二区三区四区视频| 色综合视频二区偷拍在线| 国产精品一区2区3区| 欧美日韩精品一区| 日韩一区精品| 国产成人在线亚洲欧美| 一区二区三区四区日本视频| 欧美一级片在线播放| 艳妇荡乳欲伦69影片| 另类春色校园亚洲| 国产精品久久久久久久久婷婷| 欧美片网站免费| av噜噜色噜噜久久| 99re8这里有精品热视频免费| 97自拍视频| 果冻天美麻豆一区二区国产| 九九九九九九精品| 久久99国产精品视频| 午夜精品一区二区三区四区| 超碰成人久久| 国产一区一区三区| 午夜性色一区二区三区免费视频| 久久福利一区二区| 亚洲天堂黄色| 欧美激情国产精品日韩| 蜜臀av一区二区在线免费观看| 亚洲免费黄色网| 国产精品综合二区| 人妻av一区二区| 91美女精品福利| 91麻豆精品国产91久久综合| 亚洲视频在线一区二区| 久久久久久久久久久久久久久久久 | 欧美精品福利视频| 中文字幕在线视频久| 国产精品久久久久aaaa九色| 日本一区二区三区中文字幕| 99www免费人成精品| 精品一区欧美| 伊人情人网综合| 影音先锋在线一区| 97xxxxx| 久久99九九99精品| 国产a级黄色片| 中文字幕av一区二区三区免费看| 午夜激情福利网| 欧美视频中文在线看| 亚洲天堂视频在线| 亚洲高清久久网| 91社区在线高清| 日韩经典中文字幕| se在线电影| 午夜精品久久久久久久白皮肤 | 欧美午夜精品一区二区三区| 日韩黄色三级视频| 在线观看av不卡| 性做久久久久久久| 一区二区三区视频在线| 成人av影院在线观看| 国产精品一区二区性色av| jizz性欧美23| 宅男av一区二区三区| 亚洲综合好骚| 成人免费看片载| 中文字幕一区二区在线观看| 日本在线视频中文字幕| 欧美人妖巨大在线| 青青草免费观看免费视频在线| 久久久精品2019中文字幕神马| 国产精品粉嫩| 国产精品视频福利| 在线观看日韩| 午夜国产一区二区三区| 99精品欧美一区二区三区小说| 久久福利免费视频| 欧洲国内综合视频| 日色在线视频| 午夜精品久久17c| 日本亚洲视频| 香蕉精品视频在线| 另类小说综合欧美亚洲| 欧美成人午夜精品免费| 亚洲亚洲精品在线观看| 99久久久国产精品无码网爆| 正在播放亚洲1区| 一区二区视频免费完整版观看| 精品国产一区二区三区麻豆免费观看完整版 | 天堂中文字幕av| 色综合色综合久久综合频道88| 超鹏97在线| 国产精品一区=区| 精品精品久久| 久久黄色免费看| 国产午夜久久久久| 无码人妻精品一区二区| 亚洲精品综合久久中文字幕| 白浆在线视频| 久久精品一区二区三区不卡免费视频| 亚洲婷婷在线| 污污污www精品国产网站| 亚洲成在人线免费| 蜜桃av中文字幕| 久久人91精品久久久久久不卡| 中文字幕一区二区三区中文字幕| 91精品国产毛片武则天| 国产精品一区二区三区乱码| www青青草原| 日韩一区二区麻豆国产| 羞羞污视频在线观看| eeuss一区二区三区| 国产一区久久| 捆绑裸体绳奴bdsm亚洲| 精品国产91久久久久久| 三级在线视频| 国产精品久久综合av爱欲tv| 欧美独立站高清久久| 久久婷婷中文字幕| 91丨国产丨九色丨pron| 99久热在线精品996热是什么| 日韩极品精品视频免费观看| 欧美日韩免费看片| 国产高清不卡av| 在线日韩中文| 欧美黑人欧美精品刺激| 欧洲av一区二区嗯嗯嗯啊| 麻豆传媒免费在线观看| 91视频免费在线观看| 一本久道久久久| 蜜臀久久99精品久久久久久| 欧美日韩另类一区| 性直播体位视频在线观看| 国产精品日韩一区二区免费视频 | 亚洲精品手机在线观看| 亚洲男人的天堂在线aⅴ视频| 国产成人三级在线观看视频| 91精品国产九九九久久久亚洲| 久久不见久久见免费视频7| 色www免费视频| 亚洲午夜精品17c| 欧美日韩伦理片| 成人黄色免费片| 99精品国产在热久久下载| 日韩人妻无码精品综合区| 欧美久久久久免费| 成人国产电影在线观看| 五月婷婷综合色| 粉嫩嫩av羞羞动漫久久久| 久久国产乱子伦精品| 大胆人体色综合| 神马午夜久久| 91视频福利网| 色噜噜狠狠色综合中国| 国产剧情在线| 欧美重口乱码一区二区| 国产91精品在线观看| 做爰无遮挡三级| 97成人精品视频在线观看| 婷婷综合激情| caopeng视频| 色综合欧美在线| 在线看一级片|