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/text@v0.3.0”。對於存儲在源控制存儲庫中的模塊,版本后綴也可以是提交哈希,分支標識符或源控制系統已知的其他語法,如'go get golang.org/x/text@master'。版本后綴@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/goModule@latest 的形式更新到最新版
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設置代理的方式




免責聲明!

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



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