10分鐘將你的Go工程轉換爲Go Module模式

引言
自從在Go 1.11和更高版本中引入了Go的新的依賴管理系統以來,GoLang開發人員已經接受了包版本控制解決方案。這樣做的用戶可以使用GoCenter存儲庫中的不可變公共Go 模塊,並通過更健壯、更可靠的Go Pipeline獲得更快的構建速度。

但是,將現有的項目轉換爲使用Go Module並不總是很容易,尤其是如果該項目已經嘗試過GoLang的其他包管理解決方案時。

爲了幫助GoLang社區正確地使用Go Module,我們將使用開源的etcd項目(Kubernetes使用的鍵值數據存儲)作爲示例。這是一個最佳實踐的實際示例,因爲它足夠複雜,可以展示一些常見的實踐

PS:
在上一篇關於Go語言開發的的文章中(傳送門:Go 語言依賴管理的優勢),我們介紹了Go 依賴管理的發展歷史以及Go Module如何更有效的幫助我們管理Go語言項目的依賴。今天我們重點分享如何將你的Go 項目轉換爲Go Module 項目。

Go 項目依賴管理痛點分析
傳統GO項目進行第三方模塊依賴時,往往是去下載第三方源碼,這種方式將存在以下常見問題:
1.性能及穩定性:每次下載從各大VCS系統下載源碼性能低,依賴網絡環境,穩定性差
2.一致性&可重複性:容易收到依賴源的影響,我們往往在感知不到模塊提供方的改動時,就下載了新版的代碼,兩次依賴某模塊得到的依賴不一致,往往造成前一秒還行,下一秒構建失敗的情形,尤其在持續集成系統中
3.協作:源碼方式模塊基本無版本概念,或不是語義類型,多團隊協作困難

基於以上問題及痛點,建議轉換爲Go Module 模式管理Go 項目依賴。附Go Module 基於Go Proxy進行依賴下載的原理圖:
10分鐘將你的Go工程轉換爲Go Module模式

應用Go Module方式後可以獲得以下收益:
1.可用性(標籤tag可以從VCS中刪除)
2.不變性(可以在VCS中進行更改)
3.快速:(沒有git克隆,沒有計算元數據,調用更少,性能好)
4.本地統一存儲緩存($GOPATH/pkg /mod/cache)

Go模塊轉換最佳實踐
我們以ETCD項目爲例進行轉換,這個轉換過程已通過測試用例的驗證,可以到該項目中的Pull Request中查看

步驟一:準備go.mod文件
對於以前從未使用過模塊的項目(沒有go.mod 文件),或者任何現在不推薦的依賴項管理解決方案,這個過程都非常簡單。您只需要在項目的根目錄中運行go mod tidy。這將生成一個新的、已填充好該項目依賴描述的go.mod文件。

但是,如果項目使用了那些較老的解決方案之一,比如dep、glide、govendor或godep,那麼您將需要運行go mod init來生成填充的go.mod文件。該命令支持舊格式中依賴項描述。

etcd項目確實有一個go.mod文件,儘管它從未在項目的構建系統中啓用。問題是模塊名稱沒有正確的版本標識符,因爲當前版本標記是v2+。由於語義化導入版本控制的影響,需要更改爲v3。

其包括執行以下過程:
1.更新etcd的go.mod文件以修正模塊名稱,使其包含v3後綴。
10分鐘將你的Go工程轉換爲Go Module模式
2.更新所有代碼中的Import以包含版本號。我們編寫了一個腳本,以便更容易地修改所有引用。完成後,此更改如下:
10分鐘將你的Go工程轉換爲Go Module模式

步驟二 : 啓用Go模塊
要使go客戶端能夠使用go module,需要設置GO111MODULE=on

正如我們所指出的,etcd項目已經設置了go.mod文件,有人可能認爲這已經完成了。但它沒有,而該環境變量這種缺失證實了該項目還沒有使用go module。

注意:從Go 1.13開始,這一步將不再需要,因爲Go Module將在默認情況下啓用

步驟三 : 更新測試中的導入

在上面的過程中,我們對組成etcd主模塊的go.mod文件進行了更新,以使用v3版本標記。現在主模塊被標記爲v3,我們還需要更新etcd項目的測試用例中的Import引用v3,以確保它們導入了主模塊的正確版本。

步驟四 : 其他更新

在這些更改之後,您可能希望保持良好的狀態—畢竟,應用程序模塊現在已經全部轉換爲使用go module,並使用正確的版本標記。

不過沒那麼快。一旦你開始運行測試,你會發現兩個額外的場景需要處理:

1.etcd使用了諸如golint、gosimple、staticcheck、ineffassign等靜態分析工具,但其中一些工具沒有模塊意識,無法識別模塊路徑,而無法通過必要的檢查。在etcd的這種場景下,etcd-io/etcd下並沒有v3文件夾,但是Import導入(或模塊路徑)包含v3,如etcd-io/etcd/v3。其他工具是模塊感知的,但必須在新版本的Go 1.12中可用。如果構建系統在1.11之上,那麼它們也需要遷移到1.12。

2.如果使用了protobuf之類的代碼生成器。更新.proto文件,以便使用正確版本的導入生成代碼。

步驟五 : 加入GoCenter

在構建過程中,您可能會注意到許多go get命令在etcd的不同階段執行。

爲了加快GoLang應用程序的構建時間,並確保etcd ppipeline中使用的Go Module版本的不可變性和可用性,使用GoCenter來構建etcd
只需設置GOPROXY=https://gocenter.io。(詳細原理可看上文的Go Proxy 原理圖)
總結

正如您所看到的,將Go項目轉換爲使用Go Module方式非常簡單,但是有一些細節可能會減慢您的速度。通過選擇這個具有豐富場景的項目來演示這個過程,我們相信我們達到了大多數需要處理的場景,爲您提供了一個很好的示例,覆蓋了您可能面臨的情況。

最後大家感興趣可以測試一下舊的依賴管理方式和Go Module方式的性能對比,請參考:
https://jfrog.com/blog/build-times-matter-speed-is-everything/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章