搞清楚 Go Mod的版本和偽版本,下次別亂用了
今天再跟大家嘮一下 Go Module 中軟件包的版本和偽版本的內容,因為這是一個理想很豐滿、現實很骨感的故事。
Module 的版本
關于 Go Module 依賴包的軟件版本,這塊知識就很中規中矩啦,大部分資料里也都有提及。
Go Modules模塊的版本格式為“主版本號.次版本號.修訂號”,版本號的遞增規則如下:
v1.26.0
| | |_ _ 修訂號
| |
| |_ _ _ _ 次版本號
|
|_ _ _ _ _ 主版本號
- 主版本號:當你做了不兼容的更新時變更主版本號。
- 次版本號:當你做了向下兼容的功能性更新時更改次版本號。
- 修訂號:當你做了向下兼容的問題補丁修正時更改修訂號。
不過當你在真正在項目里使用 Go Module 管理項目依賴的時候,尤其是你們公司內部的私有依賴模式時,你就會發現事情完全沒有這么簡單。
多數情況下,go.mod 文件里會有一堆依賴他們的版本會是醬嬸兒的:
golang.org/x/lint v0.0.0-20200302205851-738671d3881b
...
code.xxx.com/libs/xyz v1.0.10-0.20220805095508-6c1f3628ef7a
這個就是我們接下來要說的偽版本了。
Module 的偽版本
為什么mod 文件里有這么多偽版本 (pseudo-version) 呢,這里先跟大家插播一個小知識,大家在看技術文檔的時候經常會有偽類,偽代碼,偽版本這樣的術語,他們基本上都是在原來的詞根上加一個Pseudo前綴,代表他們不是正式的類、代碼、版本?(偽類好像不是那么回事,前端知識已經忘光了),還有那個單詞開頭的P不發音… 不過好像咱們平時交流的時候念錯了也沒事,畢竟不少程序員哥哥,都把 alter 念成了alert,也不影響我們改MySQL的表。
Go Module 生成的偽版本主要有兩種,其一是這種v0.0.0開頭的:
golang.org/x/lint v0.0.0-20200302205851-738671d3881b
這種是因為依賴模塊的代碼倉庫上不存在任何標簽,所以go get? 默認拉取的是主干分支最新一次commit對應版本的代碼,并且在go.mod文件里為模塊分配格式為 v0.0.0-主干分支最新一次commit的時間-commit哈希 這樣的一個虛擬版本。
第二種是這種非 v0.0.0 開頭的偽版本,比如:
code.xxx.com/libs/xyz v1.0.10-0.20220805095508-6c1f3628ef7a
這種一般是作為依賴包的項目本身代碼倉庫里有打標簽發布版本,可是后續我們需要更新包,在測試階段的時候在項目使用go get 模塊名@CommitHash 獲取還未正式發布的內容:
go get code.xxx.com/libs/xyz@6c1f3628ef7a
這個時候 Go Module 就會給我們在依賴已發布的版本上進行累加,然后生成偽版本,比如上面那個例子,模塊的偽版本以v1.0.10?開頭就代表模塊上一次發布的版本是v1.0.9?,你打開模塊所在的代碼倉庫看一下,一定會有一個v1.0.9的標簽在那。
這里再放一個偽版本各部分的說明圖給大家,方便理解記憶。
gomod 的偽版本規則
關于模塊的偽版本,雖然我們掌握了它的生成規則,但使用的時候一定不要自己在 go.mod 文件里去編輯,而是使用上面舉例的go get 命令,讓 Go Module 自己生成模塊的偽版本。
偽版本的亂象
針對在測試、開發階段的依賴模塊,因為不能在主干分支上打標簽,我看到網上不少資料推薦以這種方式設置版本:
// 在測試分支上打標簽
v1.2.30-test
// 在仿真分支上打標簽
v1.2.30-pre
等模塊測試通過,就可以在軟件包的master?分支打出v1.2.30?標簽,將引用模塊的項目中go.mod文件里的依賴聲明,更改成正式版本即可。
不過實際我看下來,更多的是使用偽版本的居多,而且很多線上項目在 go.mod 文件里直接就是引用的這些偽版本的模塊。
這些問題咋一看起來沒有什么事兒,但是我前段時間改了個被降本提效的團隊的項目,里面就很多這種使用依賴的偽版本,更坑的是他們沒把這個版本里的代碼合并到主干,導致我更新了一個新版本,測試的時候,報了一個類似這樣的錯。
package provided […] but not at required version
Go Module 告訴我某個包在原來的版本的模塊里,不在你聲明的版本里… 。后來花了挺長時間對比才發現原來使用的版本并沒有合并到主干分支上。
這里再次提醒一下大家,項目使用的內部依賴包,上線前一定要確定使用這些軟件包在主干上打的標簽版本,為什么再次強調一定要在主干分支上打最終的正式標簽呢... 因為如果規范不明確,真有大哥從feature分支上打正式標簽...
總結
今天給大家介紹了 Go Module 關于模塊版本管理的幾個小知識,也說了下在開發模塊時的一些亂象,咱們最好還是遵守上面說的,測試階段在測試分支打標簽,發布的時候一定要合并到主干上打正式標簽,項目不要還依賴著模塊的偽版本呢就上線了,發布前檢查一下 go.mod 及時更改過來,就不會像我這大冤種,天天給前人填坑啦。