10分鍾將你的Go工程轉換為Go Module模式


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

 

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

 

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

 

Go 項目依賴管理痛點分析

傳統GO項目進行第三方模塊依賴時,往往是去下載第三方源碼,這種方式將存在以下常見問題:

  1. 性能及穩定性:每次下載從各大VCS系統下載源碼性能低,依賴網絡環境,穩定性差
  2. 一致性&可重復性:容易收到依賴源的影響,我們往往在感知不到模塊提供方的改動時,就下載了新版的代碼,兩次依賴某模塊得到的依賴不一致,往往造成前一秒還行,下一秒構建失敗的情形,尤其在持續集成系統中
  3. 協作:源碼方式模塊基本無版本概念,或不是語義類型,多團隊協作困難

 

基於以上問題及痛點,建議轉換為Go Module 模式管理Go 項目依賴。附Go Module 基於Go Proxy進行依賴下載的原理圖:

 

 

應用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。

 

 

其包括執行以下過程:

更新etcd的go.mod文件以修正模塊名稱,使其包含v3后綴。

 

 

      2.更新所有代碼中的Import以包含版本號。我們編寫了一個腳本,以便更容易地修改所有引用。完成后,此更改如下:

 

 

 

步驟二 : 啟用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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM