[Go] 到底go get 的版號怎麼運作的?

文章推薦指數: 80 %
投票人數:10人

在Go Module 模式底下使用go get 取得套件的時候常常會有各種版號出現,例如v1.0.2、v2.0.3 +incompatible、甚至是一段hash ... Miles I’mapersonwhoisenthusiasticaboutCoding,andthat’smyjobbytheway. Home Categories Tags Archives Search About GitHub LinkedIn Pluralsight Medium RSS [Go]到底goget的版號怎麼運作的? Aug25,2020 in Go 在GoModule模式底下使用goget取得套件的時候常常會有各種版號出現,例如v1.0.2、v2.0.3+incompatible、甚至是一段hashv0.0.0-20200226145339-3e397ee01bc6。

還有取得v2版本的時候,有時候是gogetgithub.com/my/[email protected]有時候是gogetgithub.com/my/foo/[email protected]

為了搞懂這些差別,我參考了一些官方文章還有做了一些實驗,今天就來解說這些差別到底是什麼情況。

在閱讀此文章之前,建議要先了解 什麼是GoModule。

Ref:UsingGoModules 如何更改主版號(如:v1.0.0升級成v2.0.0)。

Ref:GoModules:v2andBeyond v1.2.3版號的意義。

Ref:SemanticVersioning2.0.0 Semanticimportversion在文章開始前需簡短說明一下什麼是SemanticImportVersioning。

根據SemanticVersioning版本建議規則,當主版號變更的時候,代表有破壞性更新。

以Go來說,如果這時候更新的版本還是用同樣的路徑,會造成使用的人一更新套件(package)就會壞掉。

所以會建議使用新的路徑讓兩個版本並行,並且在採用漸進式升級的方式升級成新的版本。

例如v1.x.x的路徑會是importgithub.com/my/foo,主版號升級到v2後,路徑會是importgithub.com/my/foo/v2。

而這種不同版本相容的import方式稱為SemanticImportVersioning。

當GoModule啟用後,會強制按照SemanticImportVersioning的規則,履行下列義務 版本號需要使用SemanticVersioning的方式。

例如v1.2.3,v2.7.1。

當版本號大於等於v2+的時候,在go.mod的modulepath要加上/vN,例如modulegithub.com/my/foo/v2。

此時的要使用foo/mypkg套件的時候,import會變成importgithub.com/my/foo/v2/mypkg。

如果主版號是v0或v1則modulepath與importpath不需要加上/v0或/v1 有了上敘的知識後,就開始我們今天的故事吧!! 都跟取得套件的Repository有關係這些goget版本的路徑要怎麼指定,差別都是來自於你要goget那個目標的Repository。

我目前歸納出來有四個因素會影響goget的版號 Commit 標籤(tag)。

goget會參考tag當作版號,例如v.1.2.3 是否啟用GoModule 什麼時候啟用GoModule 接下來我會分三個情境來解說這些差別 如果目標Repository沒有啟用的GoModule 如果目標Repository沒有啟用的GoModule,但是有v2+以上版本會發生什麼事情? 如果在v2+版本以上啟用GoModule的時候會發生什麼事情? 如果目標Repository沒有啟用的GoModule如果你的目標Repository沒有啟用的GoModule的話,他會根據該Repository的tag版本,下載最後一版(VersionSelection)。

例如該Repository有v3.1.2,v2.1.1,v1.2.5,v1.1.0這4個tag,執行gogetgithub.com/my/foo@latest的話,他會下載v3.1.2那個tag的版本。

假設該Repository連tag都沒有的話,則採用Pseudo-versions的方式,會去抓取master分支的最後一個commit,然後你就會看到該版本號的資訊會類似v0.0.0-20200824153131-fdc22cc4ae4b這種格式,他是由v0.0.0-{commit時間}-{commithash}所組成的。

如果目標Repository沒有啟用的GoModule,但是有v2以上版本會發生什麼事情?在看一些GoModule文章的時候,例如UsingGoModules,裡面有提到,啟用GoModule後,如果是v2以上版本的時候,需要加上/vN路徑,例如gogetgithub.com/my/foo/v2,這是當作跟v1是不同路徑的方式來抓v2的版本。

那如果目標Repository沒有啟用GoModule,都採用tag的方式標示版本,會發生什麼事情呢? 這種情況底下,的做法就不是使用/v2,而是使用@的方式指定版本就可以了,例如gogetgithub.com/my/[email protected],因為沒有啟用GoModule的模式,所以所有版本都是在同一個路徑github.com/my/foo底下。

當下載v2以上版本的時候會看到go.mod紀錄的套件會有+incompatible這個字樣,例如requiregithub.com/my/foov3.0.1+incompatible,為什麼會有+incompatible呢? 為什麼有+incompatible?我們要從Go的FAQ-HowshouldImanagepackageversionsusinggoget?說起,這是Go的建議多年的套件管控機制,裡面有一段話說 Packagesintendedforpublicuseshouldtrytomaintainbackwardcompatibilityastheyevolve.TheGo1compatibilityguidelinesareagoodreferencehere:don’tremoveexportednames,encouragetaggedcompositeliterals,andsoon.Ifdifferentfunctionalityisrequired,addanewnameinsteadofchanginganoldone.Ifacompletebreakisrequired,createanewpackagewithanewimportpath 上面畫線的重點是,如果新的版本有包含破壞性更新,則建立一個新的packageimportpath,例如github.com/my/foo/v2。

這是因為當使用同一個packageimportpath時要能夠確保相容性,不能讓使用者更新套件後,程式就壞掉。

而這建議也是從SemanticImportVersioning來的。

GoModule也有根據這個原則設計,啟用GoModule後有三個原則需要遵守 importpath不一樣會當成不同的套件 例如github.com/my/foovsgithub.com/my/foo/v2是不一樣的套件 importpath如果沒有包含/v2+的路徑的話,會當作v1或v0版本 importpath是從go.mod裡面的modulepath定義的,如modulegithub.com/my/foo/v2 簡短來說,+incompatible是指說「當使用的套件沒有啟用GoModule以及其版本號大於v1,也就是v2+的時候,我們import的路徑會是importgithub.com/my/foo,這時候根據上敘的原則2,GoModule會將其看待成v1或v0版本,這就造成與原則2產生衝突。



」 這情況下,GoModule會認為該套件並沒有使用SemanticImportVersioning的方式來管控套件,就會認為他跟v1版本是不相容的,所以加上+incompatible當作警告,但不影響使用。

如果在v2+版本以上啟用GoModule的時候會發生什麼事情?現在假設有一個情況,有一個遠端的Repositorygetgithub.com/my/foo一直沒有啟用GoModule,而且已經存在了好幾版的tag,例如v1.2.1、v1.3.5、v1.3.7、v2.1.9、v2.4.7、v3.0.1。

在這情況下gogetgithub.com/my/foo@latest自然會取得v3.0.1+incompatible的版本。

這時候Repositorygithub.com/my/foo的作者又有新版v4.0.0想要釋出,他可以有兩個選擇 繼續不啟用GoModule,新增tagv4.0.0版本。

在這情況下,當然gogetgithub.com/my/foo@latest就會取得v4.0.0+incompatible的版本 決定啟用GoModule改用符合SemanticImportVersioning的規則管理套件,然後在這情況下釋出v4.0.0版本。

在第二個選擇的情況下,gogetgithub.com/my/foo@latest你還是會取得v3.0.1+incompatible,因為根據SemanticImportVersioning的原則,主要版本變更會要求不同路徑,要用gogetgithub.com/my/foo/v4才可以取得v4.0.0的版本,而之後所有的v4版本都會釋出在github.com/my/foo/v4這個路徑底下。

如果這時候新增一個v3.2.3的版本會發生麼事情?在沒有建立gogetgithub.com/my/foo/v3的路徑,直接新增v3.2.0tag的情況下,是沒辦法gogetgithub.com/my/[email protected]版本。

會出現這種錯誤訊息 invalidversion:modulecontainsago.modfile,somajorversionmustbecompatible:shouldbev0orv1,notv3 這是因為,當啟用GoModule後的那個commit就是一個切割點。

在那個commit之前的版本v1.2.1、v1.3.5、v1.3.7、v2.1.9、v2.4.7、v3.0.1都還是放在github.com/my/foo這個路徑底下,所以你還是可以gogetgithub.com/my/[email protected]

但是在這commit之後,所有規則請按照SemanticImportVersioning來走。

想要新增一個v3的版本?請放在github.com/my/foo/v3底下。

當作者有按照規則走的時候,你就可以gogetgithub.com/my/foo/v3取得v3.2.0版本了。

在這規則底下,就是每一個主版本都放在他該存在的路徑,v2.x.x放在github.com/my/foo/v2路徑,v3.x.x放在github.com/my/foo/v3路徑,v1.x.x就放在github.com/my/foo路徑。

小結這些就是goget各種不同版號的運作機制啦。

這也是為什麼很多人,啟用GoModule後會直接跳一個主版本,否則可能會發生v3的舊版本的在github.com/my/foo路徑,啟用GoModule後的v3新版本會在github.com/my/foo/v3路徑。

到不如就把v3以前都放在github.com/my/foo未來所有版本都開始分路徑github.com/my/foo/v4+。

延伸閱讀[GoModuleswiki][TheGoBlog-UsingGoModules][FAQs—SemanticImportVersioning] TAGGEDIN GoGoModule PREVIOUS NEXT PREVIOUS NEXT ShareonFacebook ShareonTwitter ShareonGoogle+ Miles I’mapersonwhoisenthusiasticaboutCoding,andthat’smyjobbytheway. WebDeveloper Taiwan by nopostfound [C#]動態指定泛型型別 Dec30,2016 前言今天為了程式能寫好看一點,一直在糾結怎麼指定動態泛型, 但是想想實用性好像不太大,可是把這技術忘掉太可惜XD 還是記錄下來,以防忘記 [Angular]AnatomyofanAngularApplication Jan28,2017 ApplicationAngular2Application的都是由Component組合而成的,而Services則就是提供功能,可以在Component之間使用。

[Angular]AngularModules Jan30,2017 前言javascrip一直存在著Namespaces的問題,意思是指很容易將variables或者functions定義在globalnamespace。

另一方面javascript並沒有提供管理javascriptcode的方式。

Modules幫我們解決了這個問題 [Angular]BootstrappingAppComponent Feb2,2017 前言今天要說明的是Angular是如何BootstrappingComponent的。

我們會從pluralsight的課程Angular2:GettingStarted提供的Github範例做說明。

[Angular]Bindingsyntax Feb4,2017 前言要從class將資料繫結到template上面,Angular有四種方式。

內嵌繫結(Interpolation) 屬性繫結(PropertyBinding) 事件繫結(EventBinding) 雙向繫結(Two-wayBinding) [Angular]RoutingBasics Feb8,2017 前言今天要介紹AngularRouting提供了View之間切換的功能,以及如何使用跟怎麼設定。

[Angular]NavigationandRoutingAdditionalTechniques Feb9,2017 前言上一篇RoutingBasics介紹基本用法後,今天要來多加說明如何帶參數,以及如何使用程式碼navigate到其他route。

[Angular]ProtectingRouteswithGuards Feb11,2017 前言預設的情況下,任何user都是可以瀏覽到route有對應到的網址,這並不是一個好的情況。

通常會有需要一些權限的控管。

[Angular]NgModuleDecorator Feb13,2017 前言再深入講NgModule之前,要先說明App.Module的Decorator使用的一些原則。

[Angular]DiveintoAngularModules Feb14,2017 前言今天要說明如何整合多個AngularModule,讓程式碼職責跟清晰,更好維護。

103postsfound



請為這篇文章評分?