【轉】Go依賴模塊版本之Module避坑使用詳解

go GO111MODULE on 和off 還是有區別的

 

on時, 如果有import  其它包, 如果沒有 go mod init xx的話,則import 其它包一般會報錯。!!

 

 

原文: https://www.cnblogs.com/zhouj-happy/p/12463991.html

--------------

 

本文轉自:https://www.cnblogs.com/sunsky303/p/10710637.html

Go依賴模塊版本之Module避坑使用詳解

前提

對於Go的版本管理主要用過 glide,下面介紹 Go 1.11 之後官方支持的版本管理工具 mod。

關於 mod 官方給出了三個命令 go help modgo help modulesgo help module-get 幫助瞭解使用。

設置 GO111MODULE

可以用環境變量 GO111MODULE 開啓或關閉模塊支持,它有三個可選值:off、on、auto,默認值是 auto。

  • GO111MODULE=off 無模塊支持,go 會從 GOPATH 和 vendor 文件夾尋找包。
  • GO111MODULE=on 模塊支持,go 會忽略 GOPATH 和 vendor 文件夾,只根據 go.mod 下載依賴。
  • GO111MODULE=auto 在 $GOPATH/src 外面且根目錄有 go.mod 文件時,開啓模塊支持。

在使用模塊的時候,GOPATH 是無意義的,不過它還是會把下載的依賴儲存在 𝐺𝑂𝑃𝐴𝑇𝐻/𝑝𝑘𝑔/𝑚𝑜𝑑中,也會把𝑔𝑜𝑖𝑛𝑠𝑡𝑎𝑙𝑙的結果放在GOPATH/pkg/mod中,也會把goinstall的結果放在GOPATH/bin 中。

Go Mod 命令

download    download modules to local cache (下載依賴的module到本地cache))
edit        edit go.mod from tools or scripts (編輯go.mod文件)
graph       print module requirement graph (打印模塊依賴圖))
init        initialize new module in current directory (再當前文件夾下初始化一個新的module, 創建go.mod文件))
tidy        add missing and remove unused modules (增加丟失的module,去掉未用的module)
vendor      make vendored copy of dependencies (將依賴複製到vendor下)
verify      verify dependencies have expected content (校驗依賴)
why         explain why packages or modules are needed (解釋爲什麼需要依賴)

Go Mod 使用

創建 go.mod 文件

在一個新的項目中,需要執行go mod init 來初始化創建文件go.modgo.mod 中會列出所有依賴包的路徑和版本。

module github.com/xfstart07/watcher

require (
    github.com/apex/log v1.0.0
    github.com/fatih/color v1.7.0 // indirect
    github.com/fsnotify/fsnotify v1.4.7
    github.com/go-ini/ini v1.38.2
    github.com/go-kit/kit v0.7.0
    github.com/go-logfmt/logfmt v0.3.0 // indirect
)

indirect 表示這個庫是間接引用進來的。

go mod vendor 命令可以在項目中創建 vendor 文件夾將依賴包拷貝過來。

go mod download 命令用於將依賴包緩存到本地Cache起來。

顯示所有Import庫信息

go list -m -json all
  • -json JSON格式顯示
  • all 顯示全部庫

Mod Cache 路徑

默認在$GOPATH/pkg 下面:

$GOPATH/pkg/mod

我們來看看一個項目下載下來的文件形式:

mod ls -lh cache/download/github.com/go-kit/kit/@v/
total 3016
-rw-r--r--  1 a1  staff     7B Sep 29 15:37 list
-rw-------  1 a1  staff    50B Sep 29 15:37 v0.7.0.info
-rw-------  1 a1  staff    29B Sep 29 15:37 v0.7.0.mod
-rw-r--r--  1 a1  staff   1.5M Sep 29 15:37 v0.7.0.zip
-rw-r--r--  1 a1  staff    47B Sep 29 15:37 v0.7.0.ziphash

可以看出項目庫會對每個版本創建一個文件夾,文件夾下有對於版本的信息。

天坑來了:go mod 不能下載google包 ?

對於全世界絕大多數Gophers來說,Go module的引入帶來的都是滿滿的幸福感,但是對於位於中國大陸地區的Gopher來說,在這種幸福感襲來的同時,也夾帶了一絲“無奈”。其原因在於module-aware mode下,go tool默認不再使用傳統GOPATH下或top vendor下面的包了,而是在GOPATH/pkg/mod(go 1.11中是這個位置,也許以後版本這個位置會變動)下面尋找Go module的local cache。

由於衆所周知的原因,在大陸地區我們無法直接通過go get命令或git clone獲取到一些第三方包,這其中最常見的就是golang.org/x下面的各種優秀的包。但是在傳統的GOPATH mode下,我們可以先從golang.org/x/xxx的mirror站點github.com/golang/xxx上git clone這些包,然後將其重命名爲golang.org/x/xxx。這樣也能勉強通過開發者本地的編譯。又或將這些包放入vendor目錄並提交到repo中,也能實現正確的構建。

但是go module引入後,一旦工作在module-aware mode下,go build將不care GOPATH下或是vendor下的包,而是到GOPATH/pkg/mod查詢是否有module的cache,如果沒有,則會去下載某個版本的module,而對於golang.org/x/xxx下面的module,在大陸地區往往會get失敗。

有朋友可能會說,可以繼續通過其他mirror站點下載再改名啊?理論上是可行的。但是現實中,這樣做很繁瑣。我們先來看看go module的專用本地緩存目錄結構:

➜  /Users/tony/go/pkg/mod $tree -L 7
.
├── cache
│   └── download
│       └── golang.org
│           └── x
│               └── text
│                   └── @v
│                       ├── list
│                       ├── v0.1.0.info
│                       ├── v0.1.0.mod
│                       ├── v0.1.0.zip
│                       ├── v0.1.0.ziphash
│                       ├── v0.3.0.info
│                       ├── v0.3.0.mod
│                       ├── v0.3.0.zip
│                       └── v0.3.0.ziphash
└── golang.org
    └── x
        ├── text@v0.1.0
        └── text@v0.3.0

我們看到mod下的結構是經過精心設計的。cache/download下面存儲了每個module的“元信息”以及每個module不同version的zip包。比如在這裏,我們看到了golang.org/x/text這個module的v0.1.0和v0.3.0兩個版本的元信息和對應的源碼zip;同時mod下還直接存有text module的兩個版本v0.1.0和v0.3.0的源碼。

如果我們還像GOPATH mode下那種通過“mirror站下載再改名”的方式來滿足go build的需求,那麼我們需要手工分別製作某個module的不同版本的元信息以及源碼目錄,製作元信息時還要了解每個文件(比如:xx.info、xxx.mod等)的內容的生成機制,這樣的方法的“體驗”並不好。

填坑: Go module proxy

那麼問題來了:大陸Gopher如何能在go module開啓的狀態下享受go module帶來的福利呢? “解鈴還須繫鈴人”!答案就在go 1.11中。Go 1.11在引入go module的同時,還引入了Go module proxy(go help goproxy)的概念。

go get命令默認情況下,無論是在gopath mode還是module-aware mode,都是直接從vcs服務(比如github、gitlab等)下載module的。但是Go 1.11中,我們可以通過設置GOPROXY環境變量來做一些改變:讓Go命令從其他地方下載module。比如:

export GOPROXY=https://goproxy.io

一旦如上面設置生效後,後續go命令會通過go module download protocol與proxy交互下載特定版本的module。聰明的小夥伴們一定想到了。如果我們在某個國外VPS上搭建一個go module proxy server的實現,我們將可以通過該proxy下載到類似golang.org/x下面的module。與此同時,一些諸如從github.com上get package慢等次要的問題可能也被一併fix掉了。

顯然Go官方加入go proxy的初衷並非爲了解決中國大陸地區的下載qiang外包的煩惱的。但不可否認的是,GOPROXY讓gopher在versioned go的基礎上,對module和package的獲取行爲上增加了一層控制和干預能力。

資料

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