我像“小馬過河”一樣升級了我的開源系統(tǒng)
前言
我在升級之前做了比較充分的準備工作,深入研究了GoFrame V2新特性才決定升級的,并且總結(jié)了一篇文章:# ??站在開發(fā)者的角度理解框架的設計思想??。
區(qū)別于官方文檔,我是站在開發(fā)者的角度,總結(jié)分享了V2版本相比于V1版本的優(yōu)勢,實踐了我的有著130多個接口的# ??開源電商項目的升級踩坑之旅??,希望對大家有幫助。
目前開源電商系統(tǒng)V2版正在開發(fā)中,歡迎Star:https://github.com/wangzhongyang007/goframe-shop-v2
基于Gin+Gorm+VUE的集五福營銷裂變項目也在脫敏中,后面會開源出來供大家學習使用。
先說結(jié)論
我決定用我的開源項目# ??開源電商前后臺API系統(tǒng) 實踐升級之旅??。
這是一個單體項目,適合新手入門,開發(fā)了超過了130個接口,不管是新手入門還是實踐升級之旅都比較有代表性:包括了傳統(tǒng)電商需要的基本功能,也有進階高并發(fā)的解決方案。
歡迎Star:https://github.com/wangzhongyang007/goframe-shop
我最終結(jié)合自己的項目情況,決定用V2重寫開源項目,而不是用V1升級到V2,因為我的工程設計思想和V2建議的工程結(jié)構(gòu)差別很大。
經(jīng)過仔細考量后,我認為V2的工程架構(gòu)更好,雖然門檻稍高一點,但是在項目后期更易于維護。
實踐出真知
我調(diào)研實操的經(jīng)歷,還是非常有參考價值的,我的項目不適合從V1升級到V2,而是用V2重寫,并不代表你的項目不適合。這個經(jīng)歷真的就像“小馬過河”一樣。
升級之旅
下面就介紹一下我的升級之旅:
1. 首先查看之前的版本:
2. 替換依賴庫
在工程文件中進行替換,把所有的:github.com/gogf/gf/ 全部替換為:github.com/gogf/gf/v2/
3.按提示解決錯誤
替換之后嘗試運行,肯定會出錯,但是沒關(guān)系,提示什么錯誤就解決什么錯誤嘛:
我嘗試根據(jù)提示執(zhí)行 go get 相關(guān)依賴,但是并沒有生效。
4.升級框架和CLI工具
突然想到我只是替換了項目中的依賴包,但是并沒有更新GoFrame框架和GoFrame CLI工具。
而且通過查閱官方文檔得知:GoFrame是支持v1和v2同時使用的,但是官方并不建議,因為同時使用會導致維護成本很高。
注意:框架是框架,cli是cli,兩者不要混淆在一起。官方文檔有詳細介紹,不再重復闡述:官方文檔[1]
在升級CLI工具時踩了很多坑,因為通過查閱官方文檔,發(fā)現(xiàn)了很多種升級方式,但我在實踐中前幾種均未生效,最終是通過下面的方式升級成功的。
注意:如果是MacOS下使用zsh的小伙伴可能會遇到別名沖突問題,可以通過alias gf=gf來解決,運行一次之后gf工具會自動修改profile中的別名設置,用戶重新登錄(或者重開終端)就好了。
5. CLI升級成功
CLI升級安裝成功的示例圖:
查看gf cli版本 已經(jīng)更新到了v2.2.0 最新版:
6.及時備份
因為升級CLI我花了好長時間,做了各種嘗試,所以我決定及時提交git做好備份,養(yǎng)成好習慣:
在解決了CLI升級問題之后,我真的長舒了一口氣。準備迎接新的挑戰(zhàn)吧:
7.gtoken升級
解決gtoken的問題還是很簡單的,升級gtoken就可以了,正如官方文檔所說gtoken已經(jīng)全面擁抱GoFrame V2版本了:
安裝升級gtoken的教程如下:
- gopath模式:go get github.com/goflyfox/gtoken
- 使用go.mod添加:require github.com/goflyfox/gtoken latest
我是使用gopath模式安裝的,很順利;我們再繼續(xù)解決新的報錯:
8.gmvc問題
通過查閱文檔得知,gmvc已經(jīng)廢除,以后也不再支持了:
9.最新版的gf CLI生成dao
準備迎接新的挑戰(zhàn)吧,用最新版的gf CLI生成dao:
并沒有迎接到暴風雨, 而是卡住了。
原因是這樣的,正如我開篇說的:
V2版本的工程目錄做了調(diào)整,官方說:如果你的V1項目使用的是GoFrame官方推薦的工程目錄結(jié)構(gòu),可以參考最新的工程目錄結(jié)構(gòu)手動調(diào)整即可:工程目錄設計[2]。
需要注意的是,最新的cli工具不再支持舊版工程目錄的項目創(chuàng)建。
10.調(diào)整項目的目錄結(jié)構(gòu)
我們需要調(diào)整項目的目錄結(jié)構(gòu),參考鏈接如下:https://GoFrame.org/pages/viewpage.action?pageId=30740166
我在項目根目錄下,新建internal目錄,然后執(zhí)行 gf gen dao 還是很絲滑的。
11.分析V2的gf gen dao
我發(fā)現(xiàn)v2版本的cli不僅給我們生成了dao層,在model層中還細分了do層和entity層。
為什么這么設計,大家有時間可以看官方文檔:https://GoFrame.org/pages/viewpage.action?pageId=30740166
在這里我只說結(jié)論:
- dao層用于數(shù)據(jù)訪問,這是一層抽象對象,用于和底層數(shù)據(jù)庫交互,僅包含最基礎(chǔ)的 CURD 方法
- model層是結(jié)構(gòu)模型,是數(shù)據(jù)結(jié)構(gòu)管理模塊,管理數(shù)據(jù)實體對象,以及輸入與輸出數(shù)據(jù)結(jié)構(gòu)定義。
model中的do是領(lǐng)域?qū)ο?,用于dao數(shù)據(jù)操作中業(yè)務模型與實例模型轉(zhuǎn)換,由工具維護,用戶不能修改。
model中的entity是數(shù)據(jù)模型,數(shù)據(jù)模型是模型與數(shù)據(jù)集合的一對一關(guān)系,由工具維護,用戶不能修改。
12.再次備份
為了方便找回資料,我在修改目錄結(jié)構(gòu)之前也在本地做了備份,方便我一會復制粘貼代碼,小伙伴們也可以借鑒一下。
13.調(diào)整目錄結(jié)構(gòu)
官方建議的工程目錄
目錄/文件名稱 | 說明 | 描述 |
api | 對外接口 | 對外提供服務的輸入/輸出數(shù)據(jù)結(jié)構(gòu)定義。考慮到版本管理需要,往往以api/v1...存在。 |
hack | 工具腳本 | 存放項目開發(fā)工具、腳本等內(nèi)容。例如,CLI工具的配置,各種shell/bat腳本等文件。 |
internal | 內(nèi)部邏輯 | 業(yè)務邏輯存放目錄。通過Golang internal特性對外部隱藏可見性。 |
- cmd | 入口指令 | 命令行管理目錄??梢怨芾砭S護多個命令行。 |
- consts | 常量定義 | 項目所有常量定義。 |
- controller | 接口處理 | 接收/解析用戶輸入?yún)?shù)的入口/接口層。 |
- dao | 數(shù)據(jù)訪問 | 數(shù)據(jù)訪問對象,這是一層抽象對象,用于和底層數(shù)據(jù)庫交互,僅包含最基礎(chǔ)的 CURD 方法 |
- logic | 業(yè)務封裝 | 業(yè)務邏輯封裝管理,特定的業(yè)務邏輯實現(xiàn)和封裝。往往是項目中最復雜的部分。 |
- model | 結(jié)構(gòu)模型 | 數(shù)據(jù)結(jié)構(gòu)管理模塊,管理數(shù)據(jù)實體對象,以及輸入與輸出數(shù)據(jù)結(jié)構(gòu)定義。 |
- do | 領(lǐng)域?qū)ο?/p> | 用于dao數(shù)據(jù)操作中業(yè)務模型與實例模型轉(zhuǎn)換,由工具維護,用戶不能修改。 |
- entity | 數(shù)據(jù)模型 | 數(shù)據(jù)模型是模型與數(shù)據(jù)集合的一對一關(guān)系,由工具維護,用戶不能修改。 |
- service | 業(yè)務接口 | 用于業(yè)務模塊解耦的接口定義層。具體的接口實現(xiàn)在logic中進行注入。 |
manifest | 交付清單 | 包含程序編譯、部署、運行、配置的文件。常見內(nèi)容如下: |
- config | 配置管理 | 配置文件存放目錄。 |
- docker | 鏡像文件 | Docker鏡像相關(guān)依賴文件,腳本文件等等。 |
- deploy | 部署文件 | 部署相關(guān)的文件。默認提供了Kubernetes集群化部署的Yaml模板,通過kustomize管理。 |
resource | 靜態(tài)資源 | 靜態(tài)資源文件。這些文件往往可以通過 資源打包/鏡像編譯 的形式注入到發(fā)布文件中。 |
go.mod | 依賴管理 | 使用Go Module包管理的依賴描述文件。 |
main.go | 入口文件 | 程序入口文件。 |
因為我之前的目錄結(jié)構(gòu)也不是嚴格按照goFrame v1.xx示例設計的,而是根據(jù)項目的前后端需求自定義設計的。
所以意識到了:要想順利升級,工作量還是非常大的,應該需要修改很多代碼。
我參考文檔修改了自己項目的目錄:
13.1 遷移api層
我把之前寫的對外接口相關(guān)的代碼放到api層:
13.2 替換dao和model被引用的路徑
遷移之后遇到了新問題:
咱們來分析一下,目前做的操作只是:
- 通過最新的gf cli工具在項目根目錄的internal目錄下生成了新的dao和model層;
- 刪除了之前app目錄下的dao層和model層。
那咱們?nèi)痔鎿Q一下imports的目錄不就行了:
全局替換dao和model的目錄:
- 把shop/app/dao替換為:shop/internal/dao
- 把shop/app/model替換為:shop/internal/model
OK,順利的解決了上面的問題。
14.解決神奇的問題
又遇到了新的問題:提示我 xxx is not in GOROOT。
我嘗試通過用goland打開我的go/src目錄,而不是直接打開shop工程目錄,來解決問題:
這招比較好用,項目的依賴不再全部飄紅,并且goland也給出了提示:
15.解決構(gòu)建約束問題
分析一下原因:新的工程目錄使用了internal目錄,進行了約束。意思也就是除了對外暴露接口的方法放在api目錄,其他不需要對外的邏輯都要放在internal中:
好吧,啥也別說了,繼續(xù)修改:
我將之前處理業(yè)務邏輯的app目錄中的文件遷移到internal目錄中。
溫馨提示:你的項目是哪個目錄不重要,總之,按照GoFrame V2的原則,只有api目錄用于暴露給外部,不需要暴露給外部的邏輯全部放在internal目錄中:
16.項目工程目錄和V2建議的工程目錄統(tǒng)一
我結(jié)合自己的項目情況,移動和重命名了業(yè)務邏輯文件和目錄,整體還是很順滑的:
我之前的項目以library作為公共程序包,官方建議使用utility目錄,還是以官方為準吧,這樣以后在社區(qū)中溝通也能降低理解難度:
經(jīng)過目錄調(diào)整,修改后的目錄結(jié)構(gòu)和官方建議的目錄結(jié)構(gòu)基本一致了:
然后繼續(xù)各種運行,報錯,解決錯誤,整體上都比較好解決,就不做記錄了。
值得分享的經(jīng)驗就是:不要怕報錯多,整體看一遍,找找共同特點。絕大多數(shù)都是可以根據(jù)提示順利解決的問題。
17.遷移業(yè)務邏輯
在遷移業(yè)務邏輯時發(fā)現(xiàn)了新問題:
我通過研究V2的官方示例得知,service層內(nèi)部每個文件都以接口的方式定義,且service層是能夠通過代碼自動生產(chǎn)的:
如何預定義接口需要實現(xiàn)的方法呢?
答案是:在logic層編寫代碼,通過工具生成對應的service文件;在logic層的init()方法中調(diào)用service層的RegisterXXX()方法進行服務注冊,由此可見復雜的邏輯都是在logic層處理的。
18. 通過CLI生成service
通過cli生成service是非常重要的操作,因為這部分代碼必須工具生成,所以我們要先了解這個知識點,先說我的結(jié)論:
- 業(yè)務模塊之間的依賴通過接口化解耦,將原有的service分類調(diào)整為接口目錄。這樣每個業(yè)務模塊將會各自維護、更加靈活。
- 該命令通過分析給定的logic業(yè)務邏輯模塊目錄下的代碼,自動生成service目錄接口代碼。
- 生成接口及服務注冊文件
更多介紹可以查看官方文檔:接口維護-gen service[3]
19. 反思
寫到這里,目前的心得體會是一定要搞清楚v2版本的設計思想,再從v1升級到v2,否則升級到一半會導致無從下手。
因為通過V2版本的CLI工具生成的dao、model 和v1版本版本是不一致的。
同時V2版本也支持gf gen service的方式,統(tǒng)一我們的接口維護方式。
再次強烈大家看我這篇文章:# 站在開發(fā)者的角度理解框架的設計思想
從框架開發(fā)者和使用者兩個角度去學習升級V2的知識點。
20.“分水嶺”問題
到這里是一個重要的分水嶺了:是升級遷移,還是直接用V2重寫,這個沒有標準答案,咱們應該在吃透了V2新特性和工程設計思想后,結(jié)合已有的項目特點去決定。
我結(jié)合自己的項目特點,經(jīng)過仔細分析,再加上和GoFrame社區(qū)大佬們的溝通,我決定用GoFrame V2版本直接重寫,而不是在已有項目上做遷移。
因為我的項目結(jié)構(gòu)和v2的設計思想差別太大了,升級無異于重寫,甚至可能花費的精力更多。
我開源項目的工程設計是這樣的:
- 首先在app目錄新建了system目錄,用于管理多個終端:
backend對應電商平臺的后臺接口
frontend對應電商平臺的前臺接口。
- 在每個終端下又都是按照功能模塊做了區(qū)分,每個功能模塊都會創(chuàng)建一個單獨的目錄。我們以admin目錄舉例:
- admin.go:定義請求和響應的結(jié)構(gòu)體
- admin_api.go:定義了對外api的方法,調(diào)用下方admin_service.go中封裝的邏輯
- admin_service.go:編寫業(yè)務邏輯,通過dao操作DB
顯然,我的架構(gòu)設計和GoFrame V2的工程設計思路差別是很大的,經(jīng)過慎重思考,我決定基于V2最新版本重寫開源項目,也歡迎小伙們加入我們。
總結(jié)
在遇到“分水嶺”問題之前,GoFrame從v1升級到v2的過程還是比較順滑的。
我也在社區(qū)中和大家溝通了升級問題:有的大佬表示自己是新開一個項目用V2重寫的;有的大佬表示升級很簡單,就是目錄變更一下,業(yè)務邏輯還是可以用的,費不了多長時間。
這個問題就像“小馬過河”的故事一樣,大家還是要結(jié)合自己的項目情況:
- 如果你是按照V1版本建議的工程目錄或者你的設計思想本身就和V2版本比較契合,那就直接升級。
- 如果你像我一樣,已有項目的工程目錄和設計思路和V2版本有較大區(qū)別,并且在認真學習v2版本的工程實踐和新特性之后,覺得V2版本更適合你項目的后期維護迭代,那就抓緊用V2直接重寫項目吧。
相關(guān)資料
[1] 官方文檔: https://GoFrame.org/pages/viewpage.action?pageId=1115790
[2] 工程目錄設計: https://GoFrame.org/pages/viewpage.action?pageId=30740166
[3] 接口維護-gen service: https://GoFrame.org/pages/viewpage.action?pageId=49770772
[4] Go開源電商項目教程-教程大綱+開源地址: https://b23.tv/hdOpOTp
本文轉(zhuǎn)載自微信公眾號「 程序員升級打怪之旅」,作者「王中陽Go」,可以通過以下二維碼關(guān)注。
轉(zhuǎn)載本文請聯(lián)系「 程序員升級打怪之旅」公眾號。