Go modules基礎精進,六大核心概念全解析(上)

                                               

 點擊一鍵訂閱《雲薦大咖》專欄,獲取官方推薦精品內容,學技術不迷路!

 

 

 


Go 語言做開發時,路徑是如何定義的?Go Mudules又爲此帶來了哪些改變?本文將會全面介紹Go modules六大核心概念,包括了設計理念與兼容性原則等,掌握這些技術點對於管理和維護Go 模塊有重要價值。

 

 

 

上一篇文章中,筆者介紹瞭如何以經典的 hello world 爲例創建一個 Go module 模塊,需要說明的是一個模塊中是可以包含多個包(package)的,它們是可以被一起發佈、打包、版本化的。同時,Go Modules 也可以通過版本管理系統(githubgitlab)或者 goproxy 代理進行下載。在使用 Go Modules 之前,建議大家弄清楚息息相關的六大核心概念,以方便大家在後期的開發、使用過程中理解更加深入。

我們在使用 Go 語言做開發時經常會遇到像example.com/test或者example.com/test/pkg/log這樣的路徑,這些路徑到底是怎麼定義的,兩者中存在什麼關係,在 Go Modules 中又扮演着怎樣的角色呢?Go Modules 的引入對已有的包又引入了哪些新的概念,它們是如何協作的?對兼容性提出了哪些新的要求呢?讓我們一起來看一下。

 

一:模塊路徑 (Module Path)

Go 使用 “module path” 來區分不同的 module 模塊,它在 go.mod 文件中被定義,這個文件中還包含了這個模塊編譯所需的其他依賴。如果一個目錄中包含了 go.mod 文件,那麼這個目錄就是這個 Go 模塊的根目錄了。

另外,還要介紹下包(package) 這個概念,它在 Go Modules 出現之前就已經存在了。Go 模塊中的 (package)”是處於同一目錄中的一些源代碼文件的集合,這些文件將被編譯在一起。包路徑(package path是模塊路徑和子目錄(模塊根目錄的相對路徑)的組合。舉個例子,在模塊“golang.org/x/net”下的 html 目錄中有個包,這個包的路徑是 “golang.org/x/net/html”

總結下來就是: 一個代碼倉庫可以包含多個 Go 模塊,一個 Go 模塊可以包含多個 Go 包。

模塊路徑是一個 Go 模塊的規範名稱,用於區分不通的模塊。同時他還是該模塊下 Go 包的路徑前綴。理論上,模塊路徑應該至少包含兩個關鍵信息:

 

模塊的作用

哪裏獲取該模塊

 

二:版本號與兼容性原則

版本號相當於是一個模塊的只讀快照,它可以是正式的發佈版本,也可以是預發佈版本。 每個版本都以字母 v 開頭,後跟一個語義版本,例如 v1.0.0

 

總而言之,語義版本由三個由點分隔的非負整數(主要版本、次要版本和補丁版本,從左到右)組成。 補丁版本後可以跟一個以連字符開頭的可選預發佈字符串。 預發佈字符串或補丁版本後可以跟一個以加號開頭的構建元數據字符串。 例如,v0.0.0v1.12.134v8.0.5-prev2.0.9+meta 等都是有效版本。

 

版本號中的信息代表了這個版本是否是一個穩定版,是否保持了與之前版本的兼容性。

  • 當維護的模塊發生了一些不兼容變更,比如修改了外部可調用的接口或者函數時,需要對主版本號進行遞增,並且將次版本號和補丁版本號置爲零。比如在模塊中移除了一個包。
  • 在模塊中添加一些新的函數或者接口,並沒有影響模塊的兼容性時,需要對次版本號進行遞增,並且將補丁版本號置爲零。
  • 當修復了一些 bug 或者進行了一些優化時,只需要對補丁版本號進行遞增就可以了,因爲這些變更不會對已經公開的接口進行變更。
  • 預發佈後綴代表了這個版本號是一個預發佈版本。預發佈版本號的排序會在正式版本號的前面。舉個例子,v1.2.3-pre 會排列在 v1.2.3 前面。
  • 元數據後綴會在版本比對中被忽略,版本控制中的代碼庫會忽略帶有構建元數據的標籤,但在 go.mod 文件中指定的版本中會保留構建元數據。如果一個模塊還沒有遷移到 Go Modules 並且主版本號是 2 或者更高,+incompatible 後綴會被添加到版本號上。

如果一個版本的主版本號是 0 或者它有一個預發佈版本後綴,那麼這個版本被認爲是一個不穩定版本。通常,不穩定版本不受兼容性限制的,舉個例子,v0.2.0 可能和 v0.1.0 是不兼容的,v1.5.0-beta 可能和 v1.5.0 也是不兼容的。

 

Go 可以通過 tags、分支、和 commit 哈希值來獲取模塊,即使這些命名沒有遵循這些規則。在主模塊中,go 命令會自動的將這些 revision 轉化爲符合標準的版本號,其被稱爲僞版本號(pseudo-version)。舉個例子,當執行下面的命令時:

 

go get -d golang.org/x/net@daa7c041

 

Go 會講指定的 hash daa7c041 轉化爲一個僞版本號 v0.0.0-20191109021931-daa7c04131f5。在主模塊之外需要規範版本,如果 go.mod 文件中出現像 master 這樣的非規範版本,go 命令會報錯。

三:僞版本號

僞版本號是一種預發佈版本號的格式,其中包含了指定的 commit hash 值。另外,對於沒有打標籤的代碼庫,也可以使用僞版本號來表明某個版本,它可以在正式發佈某個版本之前方便的進行測試。舉個例子,每個僞版本號都有三部分組成:

  1. 基本版本前綴(vX.0.0 或 vX.Y.Z-0),它要麼源自修訂版之前的語義版本標籤,要麼源自 vX.0.0(如果沒有此類標籤)。
  2. 時間戳 (yyyymmddhhmmss),這是創建 commit 的 UTC 時間。 在 Git 中,這是 commit 提交時間。
  3. commit 標識符 (abcdefabcdef),它是提交 commit 哈希的 12 個字符的前綴,或者在 Subversion 中,是一個用零填充的修訂號。

在這三個部分之下,又分爲以下多種情況

  • 如果之前沒有基版本,那麼諸如 vX.0.0-yyyymmddhhmmss-abcdefabcdef 這樣的僞版本號將被啓用。主版本號 X 需要匹配模塊的主版本號後綴。
  • 如果之前的基版本號是一個像 vX.Y.Z-pre 這樣的預發佈版本,那麼 vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef 將被採用。
  • 如果之前的基版本號是一個像 vX.Y.Z 這樣的正式版本,那麼 vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef 將被採用,舉個例子,如果基版本號是 v1.2.3,僞版本號可能是 v1.2.4-0.20191109021931-daa7c04131f5。
  • 基於不同的基礎版本號,多個僞版本號是有可能指向同一個 commit hash 的,在對一個低於已經存在的僞版本號打標籤時,這種情況就會發生。

上面介紹的這種僞版本號攜帶了兩個非常有用的信息:

1. 僞版本號會高於這些已經存在的基礎版本號,但是會低於後面生成的其他僞版本號。

2. 有相同基礎版本前綴的僞版本按時間順序排序。

僞版本號不需要手動指定。很多 Go 命令可以接受一個 commit hash 或者分支名,然後自動將其轉化爲一個僞版本號(或者一個標籤,如果存在的話)。例如:

go get -d example.com/mod@master
go list -m -json example.com/mod@abcd1234

在本篇中,我們介紹了模塊路徑、版本號與兼容性原則、僞版本號三大概念,而在下篇我們將會繼續介紹Go Modules核心概念,包括主版本號後綴、解析包路徑到模塊路徑的流程、go.mod 文件,敬請期待。另外,騰訊雲 goproxy 企業版已經產品化,需要了解的同學可以點擊這裏

   李保坤往期精彩文章推薦:Go語言重新開始,Go Modules 的前世今生與基本使用

 

 

《雲薦大咖》是騰訊雲加社區精品內容專欄。雲薦官特邀行業佼者,聚焦於前沿技術的落地及理論實踐之上,持續爲您解讀雲時代熱點技術、探索行業發展新機。點擊一鍵訂閱,我們將爲你定期推送精品內容。

 

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