Go Modules與GOPROXY 配置


golangd 配置go mod 在博文底部

摘抄自https://studygolang.com/articles/24544 go語言中文網 在原基礎博客整理增加知識點 讓你徹底名表go mod
隨着Go 1.13發布,GOPROXY默認值proxy.golang.org在中國大陸不能被訪問。

七牛雲順勢推出goproxy.cn,以利於中國開發者更好使用Go Modules,它是非盈利性的項目,首先感謝七牛雲。

Windows下使用教程:

(1)升級到Go1.13

(2)運行<go env -w GO111MODULE=on> //開啟mod

(3)運行<go env -w GOPROXY=https://goproxy.cn,direct> //設置七牛雲goproxy代理

可以通過運行go env查看(2)、(3)步驟是否設置成功

在這里插入圖片描述
(4)在項目跟目錄下執行go mod init <OPTIONAL_MODULE_PATH>

執行成功后生成go.mod文件

其他指令

go get -u //更新現有的依賴
go mod tidy //整理模塊(拉取缺少的模塊,移除不用的模塊)
go mod download//下載依賴包
go mod graph //打印現有依賴結構
go mod vendor //將依賴復制到vendor下
go mod verify //校驗依賴
go.mod文件解析
module:模塊名稱,使用指令go mod init <OPTIONAL_MODULE_PATH>可設置
require:依賴包列表以及版本
exclude:禁用依賴包列表
replace:替換依賴包列表
go:go版本號

goland編輯器中配置go mod

在goland的setting里設置啟用Go Modules
goland Preference->Go->Go Modules(vgo) -> Enable Go Modules(vgo)intergration

在這里插入圖片描述

勾選 Enable Go Modules(vgo)intergration 之后 ,

proxy配置(參考上圖)
https://goproxy.cn
點擊apply (應用)ok 即可。

______________________________________________________________
______________________________________________________________


gomod 的相關知識 摘抄自go 夜讀 (author:盛傲飛)
在這里插入圖片描述
go.mod

module sss

go 1.13

require (
	github.com/astaxie/beego v1.12.0
	github.com/go-sql-driver/mysql v1.4.1
	github.com/julienschmidt/httprouter v1.3.0
	github.com/micro/examples v0.2.0
	github.com/micro/go-micro v1.18.0
)

go.mod 是啟用了 Go moduels 的項目所必須的最重要的文件,它描述了當前項目(也就是當前模塊)的元信息,每一行都以一個動詞開頭,目前有以下 5 個動詞:

  • module:用於定義當前項目的模塊路徑。
  • go:用於設置預期的 Go 版本。
  • require:用於設置一個特定的模塊版本。
  • exclude:用於從使用中排除一個特定的模塊版本。
  • replace:用於將一個模塊版本替換為另外一個模塊版本。

這里的填寫格式基本為包引用路徑+版本號,另外比較特殊的是 go $version,目前從 Go1.13 的代碼里來看,還只是個標識作用,暫時未知未來是否有更大的作用。
go.sum
go.sum 是類似於比如 dep 的 Gopkg.lock 的一類文件,它詳細羅列了當前項目直接或間接依賴的所有模塊版本,並寫明了那些模塊版本的 SHA-256 哈希值以備 Go 在今后的操作中保證項目所依賴的那些模塊版本不會被篡改。

example.com/apple v0.1.2 h1:WX...
example.com/apple v0.1.2/go.mod h1:xHW...
example.com/banana v1.2.3/go.mod h1:HS... 
...
example.com/apple v0.1.2 h1:WXk...
example.com/apple v0.1.2/go.mod h1:xH...

前者為 Go modules 打包整個模塊包文件 zip 后再進行 hash 值,而后者為針對 go.mod 的 hash 值。他們兩者,要不就是同時存在,要不就是只存在 go.mod hash。

那什么情況下會不存在 zip hash 呢,就是當 Go 認為肯定用不到某個模塊版本的時候就會省略它的 zip hash,就會出現不存在 zip hash,只存在 go.mod hash 的情況。

GO111MODULE
這個環境變量主要是 Go modules 的開關,主要有以下參數:

  • auto:只在項目包含了 go.mod 文件時啟用 Go modules,在 Go 1.13 中仍然是默認值,詳見 :golang.org/issue/31857。
  • on:無腦啟用 Go modules,推薦設置,未來版本中的默認值,讓 GOPATH 從此成為歷史。
  • off:禁用 Go modules。

GOPROXY
這個環境變量主要是用於設置 Go 模塊代理,主要如下:

  • 它的值是一個以英文逗號 “,” 分割的 Go module proxy 列表(稍后講解)
  • 作用:用於使 Go 在后續拉取模塊版本時能夠脫離傳統的 VCS 方式從鏡像站點快速拉取。它擁有一個默認值,但很可惜 proxy.golang.org 在中國無法訪問,故而建議使用 goproxy.cn 作為替代。
  • 設置為 “off” :禁止 Go 在后續操作中使用任 何 Go module proxy。

剛剛在上面,我們可以發現值列表中有 “direct” ,它又有什么作用呢?
其實值列表中的 “direct” 為特殊指示符,用於指示 Go 回源到模塊版本的源地址去抓取 (比如 GitHub 等),當值列表中上一個 Go module proxy 返回 404 或 410 錯誤時,Go 自動嘗試列表中的下一個,遇見 “direct” 時回源,遇見 EOF 時終止並拋出類似 “invalid version: unknown revision…” 的錯誤。

GOSUMDB
它的值是一個 Go checksum database,用於使 Go 在拉取模塊版本時(無論是從源站拉取還是通過 Go module proxy 拉取)保證拉取到的模塊版本數據未經篡改,也可以是“off”即禁止 Go 在后續操作中校驗模塊版本

  • 格式: SUMDB_NAME+PUBLIC_KEY或SUMDB_NAME+PUBLIC_KEY SUMDB_URL。
  • 擁有默認值: sum.golang.org (之所以沒有按照上面的格式是因為 Go 對默認值做了特殊處理)。
  • 可被 Go module proxy 代理 (詳見:Proxying a Checksum Database)。
  • GOSUMDB 的默認值在中國無法訪問,故而更加建議將 GOPROXY 設置為 goproxy.cn,因為 goproxy.cn 支持代理 sum.golang.org。

Go Checksum Database
Go checksum database 主要用於保護 Go 不會從任何源頭拉到被篡改過的非法 Go 模塊版本,其作用(左)和工作機制(右)如下圖:
在這里插入圖片描述
如果有興趣的小伙伴可以看看 Proposal: Secure the Public Go Module Ecosystem,有詳細介紹其算法機制,如果想簡單一點,查看 go helpmodule-auth 也是一個不錯的選擇。

GONOPROXY/GONOSUMDB/GOPRIVATE
這三個環境變量都是用在當前項目依賴了私有模塊,也就是依賴了由 GOPROXY 指定的 Go module proxy 或由 GOSUMDB 指定 Go checksum database 無法訪問到的模塊時的場景,他們具有如下特性:

  • 它們三個的值都是一個以英文逗號 “,” 分割的模塊路徑前綴,匹配規則同 path.Match。

  • 其中 GOPRIVATE 較為特殊,它的值將作為 GONOPROXY 和 GONOSUMDB 的默認值,所以建議的最佳姿勢是只是用 GOPRIVATE。

在使用上來講,比如 GOPRIVATE=*.corp.example.com 表示所有模塊路徑以 corp.example.com 的下一級域名 (如 team1.corp.example.com) 為前綴的模塊版本都將不經過 Go module proxy 和 Go checksum database,需要注意的是不包括 corp.example.com 本身。
Global Caching
這個主要是針對 Go modules 的全局緩存數據說明,如下:

  • 同一個模塊版本的數據只緩存一份,所有其他模塊共享使用。
  • 目前所有模塊版本數據均緩存在 $GOPATH/pkg/mod和 $GOPATH/pkg/sum 下,未來或將移至 $GOCACHE/mod和 $GOCACHE/sum 下( 可能會在當 $GOPATH 被淘汰后)。
  • 可以使用 go clean-modcache 清理所有已緩存的模塊版本數據。

另外在 Go1.11 之后 GOCACHE 已經不允許設置為 off 了,我想着這也是為了模塊數據緩存移動位置做准備,因此大家應該盡快做好適配。

++++++++++++++++++++++++=+++++++++++++++++=++++++++++++++++++++++++=+++++++++++++++++=++++++++++++++++++++++++=+++++++++++++++++=++++++++++++++++++++++++=+++++++++++++++++=++++++++++++++++++++++++=+++++++++++++++++=++++++++++++++++++++++++=+++++++++++++++++=++++++++++++++++++++++++=+++++++++++++++++=++++++++++++++++++++++++=+++++++++++++++++=++++++++++++++++++++++++=+++++++++++++++++=++++++++++++++++++++++++=+++++++++++++++++=

快速遷移項目至 Go Modules

在這里插入圖片描述

  • 升級到 Go 1.13。

  • 讓 GOPATH 從你的腦海中完全消失,早一步踏入未來。

    • 修改 GOBIN 路徑(可選)。
    • 打開 Go modules 的開關。
    • 設置 GOPROXY。
  • 按照你喜歡的目錄結構重新組織你的所有項目。

  • 在你項目的根目錄下執行 go mod init<OPTIONAL_MODULE_PATH> 以生成 go.mod 文件。

  • 想辦法說服你身邊所有的人都去走一下前四步。

遷移后 go get 行為的改變

這里我們注意到有兩點比較特別,分別是:
在這里插入圖片描述

  • 第一點:為什么 “拉取 hash 為 342b231 的 commit,最終會被轉換為 v0.3.2” 呢。這是因為雖然我們設置了拉取 @342b2e commit,但是因為 Go modules 會與 tag 進行對比,若發現對應的 commit 與 tag 有關聯,則進行轉換。
  • 第二點:為什么不建議使用 go mod vendor,因為 Go modules 正在淡化 Vendor 的概念,很有可能 Go2 就去掉了。

使用 Go Modules 時常遇見的坑

坑 1: 判斷項目是否啟用了 Go Modules

在這里插入圖片描述

坑 2: 管理 Go 的環境變量

在這里插入圖片描述
這里主要是提到 Go1.13 新增了 go env-w 用於寫入環境變量,而寫入的地方是 os.UserConfigDir 所返回的路徑,需要注意的是 go env-w 不會覆寫。

坑 3: 從 dep、glide 等遷移至 Go Modules

在這里插入圖片描述
這里主要是指從舊有的依賴包管理工具(dep/glide 等)進行遷移時,因為 BUG 的原因會導致不經過 GOPROXY 的代理,解決方法有如下兩個:

  • 手動創建一個 go.mod 文件,再執行 go mod tidy 進行補充。
  • 上代理,相當於不使用 GOPROXY 了。

坑 4:拉取私有模塊

在這里插入圖片描述
這里主要想涉及兩塊知識點,如下:

  • GOPROXY 是無權訪問到任何人的私有模塊的,所以你放心,安全性沒問題。
  • GOPROXY 除了設置模塊代理的地址以外,還需要增加 “direct” 特殊標識才可以成功拉取私有庫。

坑 5:更新現有的模塊

在這里插入圖片描述

坑 6:主版本號

在這里插入圖片描述

Q:使用 Go modules 時可以同時依賴同一個模塊的不同的兩個或者多個小版本(修訂版本號不同)嗎?

A:不可以的,Go modules 只可以同時依賴一個模塊的不同的兩個或者多個大版本(主版本號不同)。比如可以同時依賴 example.com/foobar@v1.2.3 和 example.com/foobar/v2@v2.3.4,因為他們的模塊路徑(module path)不同,Go modules 規定主版本號不是 v0 或者 v1 時,那么主版本號必須顯式地出現在模塊路徑的尾部。但是,同時依賴兩個或者多個小版本是不支持的。比如如果模塊 A 同時直接依賴了模塊 B 和模塊 C,且模塊 A 直接依賴的是模塊 C 的 v1.0.0 版本,然后模塊 B 直接依賴的是模塊 C 的 v1.0.1 版本,那么最終 Go modules 會為模塊 A 選用模塊 C 的 v1.0.1 版本而不是模塊 A 的 go.mod 文件中指明的 v1.0.0 版本。

這是因為 Go modules 認為只要主版本號不變,那么剩下的都可以直接升級采用最新的。但是如果采用了最新的結果導致項目 Break 掉了,那么 Go modules 就會 Fallback 到上一個老的版本,比如在前面的例子中就會 Fallback 到 v1.0.0 版本。


免責聲明!

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



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