1. 程式人生 > >GO1.11 Module全攻略

GO1.11 Module全攻略

為了不再每次新建工程都要拷貝一大堆Github的庫檔案。特意學習了下1.11的最新庫檔案管理模組,Module。

之前的管理方式有Vendor,GoVendor,GoDep,Dep,Glide等等。因為官方說1.12還會遲滯Modue這個功能,所以之前的就不必學了,況且之前的這些Github專案的上傳者看到Go出了官方工具後,紛紛表態不再更新自己的庫管理專案,最多維護一段時間。

所以來Go Module。一勞永逸。

1.先說GOPATH環境變數。理解了GOPATH變數,就明白啟用GOModule之前和之後的變化。

GOPATH用來解析import語句。列出了查詢Go程式碼的位置。如果設定就是設定的值,如果沒有設定則使用預設值,預設值使用go env GOPATH可檢視值。GOPATH設定的目錄下有固定結構:

src:目錄包含原始碼。src下面的路徑確定匯入路徑或可執行檔名。

pkg:目錄包含已安裝的包物件。每個目標作業系統和體系結構對都有自己的子目錄pkg(pkg / GOOS_GOARCH)。

bin目錄儲存已編譯的命令。每個命令都以其源目錄命名,但僅以最終元素命名,而不是整個路徑。

也就是說,DIR / src / foo / quux中帶有源的命令安裝在DIR / bin / quux中,而不是DIR / bin / foo / quux中。剝離“foo /”字首,以便您可以將DIR / bin新增到PATH以獲取已安裝的命令。如果設定了GOBIN環境變數,則命令將安裝到它命名的目錄而不是DIR / bin。GOBIN必須是絕對的道路。

在某些IDE中除了會引入環境變數的GOPATH所代表的值,還可以設定屬於當前專案自己的多個GOPATH值。

Go搜尋GOPATH中列出的每個目錄以查詢原始碼,但新包始終下載到列表中的第一個目錄中。

需要注意的是:在1.11版本中,GOPATH不再用於解析。但仍然用於儲存下載的原始碼(在GOPATH / pkg / mod中)和編譯的命令(在GOPATH / bin中)。

2.先設定GO111MODULE,有三個值,on, off , auto, on 是強制所有Go專案都啟用Module,off相反,auto則根據當前專案是否在GOPATH / src下,是則不開啟,否在開啟。

3.在這裡Go module的使用分為幾種情況,

a.1.10使用非Go Module的管理模式,現在要改造成符合GoModule管理的形式。

b.直接新建工程,使用GoModule模式。

其實這兩種情況大同小異,唯一不同的是目錄結構,舊的專案中肯定包含src目錄,新的目錄不必再必須新建src這個目錄。

下面就以第一種方式a的情況為例。看看怎麼使用go module. 

A.第一種方式直接在之前舊目錄的src下main.go所在的目錄中 開啟cmd,輸入 go init module名,這裡以X5為例, 就可以了會發現新生成了一個go.mod檔案,裡面第一行內容為 module x5.

PS:值得一提的是在已經使用現有依賴關係管理工具(如godep,glide或dep)的專案中,“go mod init”還將新增與現有配置匹配的require語句。

B.一旦go.mod檔案存在,就不需要額外的步驟:像'go build','go test',甚至'go list'這樣的命令會根據需要自動新增新的依賴項來滿足匯入。

這些命令一旦執行,(在包含讓main函式執行的目錄中執行),則開始在當前目錄查詢mod檔案,或者當前目錄的父目錄,或父目錄的父目錄,來查詢各個模組的根目錄,最後根據程式碼中的引用確定在mod檔案中加入哪些依賴項。

需要注意的是依賴模組中的任何replace和exclude語句都將被忽略。因此,replace和exclude語句允許主模組完全控制其自己的構建,而不受依賴項的完全控制。所以,主模組依賴的包裡的庫版本其實是不起作用的,最終起作用的是放在主模組的mod檔案中的版本。

mod檔案 通過 require,replace,exclude三個命令來使用精確的軟體包。

提供構建包的模組集稱為“構建列表”。構建列表最初僅包含主模組。然後,go命令以遞迴方式向列表新增列表中已有模組所需的確切模組版本,直到沒有任何內容可新增到列表中。如果將特定模組的多個版本新增到列表中,則最後僅保留最新版本(根據語義版本排序)以用於構建。

'go list'命令提供有關主模組和構建列表的資訊。例如:

go list -m#主模組的列印路徑
go list -m -f = {{.dir}} #print主模組的根目錄
go list -m all #print build list

4.go.mod檔案是程式設計師和工具可讀和可編輯的。go命令本身會自動更新go.mod檔案,以維護標準格式和require語句的準確性。

任何之前不存在的import匯入,go命令都會查詢包含該匯入的模組,並自動將該模組的最新版本新增到go.mod中。因此,在大多數情況下,只需在原始碼中新增匯入並執行“go build”,“go test”,甚至“go list”即可:作為分析包的一部分,go命令將發現並解析匯入並更新go.mod檔案。

任何Go命令都可以確定缺少哪些模組,並且必須新增。如果確定不再需要某個包,在通過各種編譯引數編譯全部模組之後(架構,作業系統,構建引數),想要刪除這些包,使用go mod tidy,這個命令,它會新增任何缺少的模組並刪除不必要的模組。

// indirect命令,是不是由主mod直接引用的包,而是由其他mod間接引用的包。由這個標記的時候,如果之後新增了直接引用的該mod,會刪除上面的間接引用。

原文 Indirect requirements only arise when using modules that fail to state some of their own dependencies or when explicitly upgrading a module's dependencies ahead of its own stated requirements. 不太明白。

因為這種自動維護,go.mod中總是最新的。

'go get'命令更新go.mod以更改構建中使用的模組版本。升級一個模組可能意味著升級其他模組,同樣一個模組的降級可能意味著降級其他模組。'go get'命令也會產生這些隱含的變化。如果直接編輯go.mod,“go build”或“go list”等命令將假定預設是要升級的,並自動進行任何隱含的升級並更新go.mod以反映它們。

'go mod'命令提供了用於維護和理解模組和go.mod檔案的其他功能。

go build -mod 標誌提供了對go.mod更新和使用的額外控制。

-mod=readonly 不允許自動更新。但當對go.mod需要有任何修改時,會失敗。

即使使用-mod = readonly,“go get”命令仍然允許更新go.mod,

並且“go mod”命令不接受-mod標誌(或任何其他構建標誌)。

如果使用-mod = vendor呼叫,則go命令假定供應商目錄包含正確的依賴項副本,並忽略go.mod中的依賴項描述。

就是不再在GOPATH中查找了,而在執行go命令的目錄中的vendor目錄中查詢。

5.mod中的檔案版本。

go.mod檔案和go命令通常使用語義版本作為描述模組版本的標準形式,因此可以比較版本以確定哪個版本應該比其他版本更早或更晚。通過在底層源儲存庫中標記修訂版來引入類似v1.2.3的模組版本。可以使用像v0.0.0-yyyymmddhhmmss-abcdefabcdef這樣的“偽版本”來引用未標記的修訂,其中時間是UTC的提交時間,最後的字尾是提交雜湊的字首。時間部分確保可以比較兩個偽版本以確定稍後發生的版本,提交雜湊標識基礎提交,並且字首(在此示例中為v0.0.0-)是從提交圖中的最新標記版本派生的在此提交之前。

有三種偽版本形式:

當目標提交之前沒有具有適當主要版本的早期版本化提交時,將使用vX.0.0-yyyymmddhhmmss-abcdefabcdef。(這最初是唯一的形式,所以一些較舊的go.mod檔案使用這種形式,即使對於跟隨標籤的提交也是如此。)

當目標提交之前的最新版本化提交是vX.YZ-pre時,使用vX.YZ-pre.0.yyyymmddhhmmss-abcdefabcdef。

當目標提交之前的最新版本化提交是vX.YZ時,使用vX.Y.(Z + 1)-0.yyyymmddhhmmss-abcdefabcdef。

偽版本永遠不需要手動輸入:go命令將接受普通提交雜湊並自動將其轉換為偽版本(或標記版本,如果可用)。此轉換是模組查詢的示例。

這種版本是和已標記的版本相對的,已標記的版本很明確的指出,v1.2.3但未標明的就要用上面這種形式的版本。

 

6.模組驗證和下載

go命令和go.mod一起維護一個名為go.sum的檔案。

其中包含特定模組版本內容的預期加密校驗和。每次使用依賴項時,如果缺少,則將其校驗和新增到go.sum,或者需要匹配go.sum中的現有條目。

go命令維護下載包的快取,並在下載時計算並記錄每個包的加密校驗和。在正常操作中,go命令會針對主模組的go.sum檔案檢查這些預先計算的校驗和,而不是在每次命令呼叫時重新計算它們。'go mod verify'命令檢查模組下載的快取副本是否仍然匹配記錄的校驗和和go.sum中的條目。

根據GOPROXY環境變數的設定,go命令可以從代理獲取模組,而不是直接連線到源控制系統。

關於GOPROXY,go 命令預設從版本控制系統中下載modules,就像go get一樣。GOPROXY允許對資料來源的更深的控制。

如果GOPROXY 沒設定值,或設為空字串,或者 “direct”,downloads還是會直接從版本控制系統中下載。

GOPROXY身為off,則停止從任何地方下載。

否則GOPROXY則被期望作為module代理的URL,這樣go命令將會從從這個代理獲取全部的modules。不管資料來源地址如何,但下載的modules必須符合go.sum中已經出現的記錄。

一個Go module代理是一個具有特定形式的URL,且可響應GET請求的Web伺服器。請求沒有任何引數,所以即使是一個檔案系統的網路服務(file://URL)也可以做module代理。


GET $GOPROXY/<module>/@v/list returns a list of all known versions of the
given module, one per line.

GET $GOPROXY/<module>/@v/<version>.info returns JSON-formatted metadata
about that version of the given module.

GET $GOPROXY/<module>/@v/<version>.mod returns the go.mod file
for that version of the given module.

GET $GOPROXY/<module>/@v/<version>.zip returns the zip archive
for that version of the given module.

為了避免在大小寫敏感的檔案系統中出現問題,<module>和<version>元素被大小寫編碼,使用!+對應的小寫字母替換 每一個大寫字母。如:github.com/Azure ->github.com/!azure

未來對於某個模組的資料結構,可能會被擴充套件為JSON形式的元資料,

type Info struct {

     Version string    // version string

     Time time.Time // commit time

}

 

某個模組的某個版本的壓縮檔案,是一個標準的zip檔案,包括檔案樹響應返回的module的原始碼和關聯檔案。壓縮檔案使用嚴格分開的路徑,並且壓縮檔案中的每個檔案的路徑都以 <module>@<version>/開頭,module和version被直接替換,且沒有大小寫轉化。Module的根目錄檔案系統響應在壓縮檔案中的<module>@<version>/字首。

每次從版本控制系統中直接下載,go 命令綜合了具體的info,mod和zip檔案。並且把他們儲存在本地cache$GOPATH/pkg/mod/cache/download中,就像是直接從代理中下載下來一樣。

快取的佈局和代理的URL空間一模一樣,如果使用$GOPATH/pkg/mod/cache/download作為目錄,使用https://example.com/proxy 可以讓其他使用者訪問那些已經快取的modules通過設定GOPROXY=“https://example.com/proxy.”

7.Module和Vendor

當使用go module時,還記得之前的GO111MODULE環境變數嗎?

go命令完全忽略vendor目錄。

預設情況下,go命令通過從其源下載模組並使用下載的副本來滿足依賴性(在驗證之後,如上一節中所述)。為了允許與舊版本的Go進行互操作,或者為了確保用於構建的所有檔案一起儲存在單個檔案樹中,“go mod vendor”在主模組的根目錄中建立一個名為vendor的目錄並存儲在那裡來自依賴模組的包,這些包是支援主模組中包的構建和測試所需的。

要使用主模組的頂級供應商目錄來構建以滿足依賴性(禁止使用常用網路源和本地快取),請使用“go build -mod = vendor”。請注意,僅使用主模組的頂級供應商目錄; 其他位置的供應商目錄仍被忽略。

8.模組感知go get

'go get'命令根據go命令是在模組感知模式還是傳統GOPATH模式下執行來改變行為。即使在傳統GOPATH模式下,此幫助文字也可以作為“go help module-get”訪問,它描述了“go get”,因為它在模組感知模式下執行。

用法:go get [-d] [-m] [-u] [-v] [-insecure] [build flags] [packages]

獲取解析並將依賴項新增到當前開發模組,然後構建並安裝它們。

第一步是解決要新增的依賴項。

對於每個命名的包或包模式,get必須決定使用哪個版本的相應模組。預設情況下,get選擇最新的標記發行版本,例如v0.4.5或v1.2.3。如果沒有標記的發行版本,請選擇最新的標記預釋出版本,例如v0.0.1-pre1。如果根本沒有標記版本,請選擇最新的已知提交。

可以通過在package引數中新增@version字尾來覆蓋此預設版本選擇,如“go get golang.org/x/[email protected]”。對於儲存在源控制儲存庫中的模組,版本字尾也可以是提交雜湊,分支識別符號或源控制系統已知的其他語法,如'go get golang.org/x/[email protected]'。版本字尾@latest顯式請求上述預設行為。

如果正在考慮的模組已經是當前開發模組的依賴項,則get將更新所需的版本。指定早於當前所需版本的版本是有效的,並降低依賴性。版本字尾@none表示應完全刪除依賴項。

雖然預設使用包含命名包的模組的最新版本,但它不使用該模組的最新版本的依賴項。相反,它更喜歡使用該模組請求的特定依賴版本。例如,如果最新的A需要模組B v1.2.3,而B v1.2.4和v1.3.1也可用,那麼'go get A'將使用最新的A但是然後使用B v1.2.3,按照A的要求。(如果對特定模組有競爭要求,那麼'go get'通過獲取最大請求版本來解決這些要求。)

-u標誌指示get更新依賴關係以在可用時使用較新的次要或補丁版本。繼續前面的例子,'go get -u A'將使用最新的A與B v1.3.1(不是B v1.2.3)。

-u = patch標誌(不是-u patch)指示獲取更新依賴關係以在可用時使用更新的補丁版本。繼續前面的例子,'go get -u = patch A'將使用最新的A和B v1.2.4(不是B v1.2.3)。

通常,新增新的依賴項可能需要升級現有的依賴項以保持工作的構建,並且“go get”會自動執行此操作。同樣,降級一個依賴關係可能需要降低其他依賴關係,“go get”也會自動執行此操作。

在解析,升級和降級模組以及更新go.mod之後,-m標誌指示get停在這裡。使用-m時,每個指定的包路徑也必須是模組路徑,而不是模組根目錄下的包的匯入路徑。

-insecure標誌允許從儲存庫中獲取並使用不安全的方案(如HTTP)解析自定義域。謹慎使用。

第二步是下載(如果需要),構建和安裝命名包。

如果引數命名模組但不命名包(因為模組的根目錄中沒有Go原始碼),則跳過該引數的安裝步驟,而不是導致構建失敗。例如,即使沒有與該匯入路徑對應的程式碼,'go get golang.org/x/perf'也會成功。

請注意,允許使用包模式,並在解析模組版本後進行擴充套件。例如,'go get golang.org/x/perf/cmd / ...'新增最新的golang.org/x/perf,然後在最新版本中安裝命令。

-d標誌指示get下載構建命名包所需的原始碼,包括下載必要的依賴項,但不構建和安裝它們。

如果沒有包引數,則“go get”將應用於主模組,並應用於當前目錄中的Go包(如果有)。特別是,'go get -u'和'go get -u = patch'更新主模組的所有依賴項。沒有包引數也沒有-u,'go get'不僅僅是'go install','go get -d'不僅僅是'go list'。

有關模組的更多資訊,請參閱“go help modules”。

有關指定包的更多資訊,請參閱“go help packages”。

本文描述了使用模組管理原始碼和依賴項的行為。如果go命令在GOPATH模式下執行,則get的標誌和效果的細節會發生變化,就像'go help get'一樣。請參閱'go help modules'和'go help gopath-get'。

另見:go build,go install,go clean,go mod。

 

PS:有些go庫檔案下載失敗,ru golang.org/x/image

這是後可以通過設定代理proxier和 shadowsocket來訪問,如果設定好之後,cmd不起作用。

在cmd執行以下程式碼。

netsh winhttp import proxy source=ie

上面的是自己寫的,翻譯的Golang 1.11版本的的釋出日誌。

 

更新庫:

 

go get github.com/jtianling/[email protected] 的形式更新到最新版
go get -u 的形式升級所有的依賴庫

 

下面為轉載。

====================================================================================

為CMD設定代理

公司網路出口有代理伺服器。通常Windows介面使用Proxifier同一處理代理。但是cmd命令列模式執行pip顯示超時,Proxifier監控網路埠沒有代理阻斷。

臨時代理方案

開啟cmd設定代理:

set http_proxy=http://0.0.0.0:8000
set https_proxy=http://0.0.0.0:8000

設定完成後問題解決
***0.0.0.0改成自己的代理伺服器和埠

永久設定方案

先設定好IE代理。
cmd執行如下命令:

netsh winhttp import proxy source=ie

Atom代理

Atom是個不錯的ide工具,如果給atom設定代理,也要用cmd設定代理的方式



作者:寂寞傑羅
連結:https://www.jianshu.com/p/1fd879703aeb