淺談GoPath和Go Modules包管理


1、概述

大多數語言都有“依賴”、“包”等概念,Go語言的依賴處理經歷了幾次變革

最早的時候,Go所依賴的所有的第三方庫都放在GOPATH這個目錄下面

v1.5開始開始引入vendor模式,如果項目目錄下有vendor目錄,那么go工具鏈會優先使用vendor內的包進行編譯、測試等

v1.11開始,引入了Go Module 作為依賴解決方案,到v1.14宣布Go Module已經可以用於生產環境,到v1.16版本開始Go Module默認開啟

2、GOPATH介紹

2.1 GOPATH目錄

GOPATH是什么,輸入如下命令查看

# go env GOPATH
GOPATH="/Users/ssgeek/go"

進入到該目錄下,目錄結構如下

# cd `go env GOPATH`
# tree -L 2 .
.
├── bin
│   ├── dlv
│   ├── go-outline
│   ├── gomodifytags
│   ├── gopkgs
│   ├── goplay
│   ├── gopls
│   ├── gotests
│   ├── impl
│   └── staticcheck
├── pkg
│   ├── mod
│   └── sumdb
└── src
    └── github.com
    ...

三個目錄中存放的文件說明如下

bin //用來存放編譯后的可執行文件
pkg //用於存放編譯后生成的歸檔文件
src //用來存放go源碼文件

2.2 GOPATH的缺點

在使用GOPATH的模式下,我們需要將應用代碼存放在固定的$GOPATH/src目錄下,並且如果執行go get來拉取外部依賴會自動下載並安裝到$GOPATH目錄下

第三方套件只要不是官方庫,都需要放置在GOPATH/src的路徑下才可以使用

go get最常用在當我們想用別人公開在GitHub上的套件,可以幫我們從網絡cloneGOPATH/src里面。雖然這樣很方便,但是會發現GOPATH/src下會很復雜,除了有你自己開發的代碼目錄,同時也包含其他第三方庫的專屬目錄

我們給不同的項目設置不同的GoPath,優點非常明顯:

便於管理項目,每個項目都是不同的GoPath,這對於我們管理多個Golang項目而言,能夠非常清晰的處理項目結構。如果我們把所有項目都放在同一個GoPathsrc包下,那么項目的結構就會變得非常混亂,難以管理

但是當我們需要依賴第三方的包的時候,不同的項目設置不同的GoPath的缺點也非常明顯:

  1. 第三方依賴的包和我們自己的Golang包混在一起,會給我們的項目文件管理帶來一定的麻煩
  2. 不同的GoPath都需要下載依賴,那么磁盤中重復的依賴就會非常多,會占用我們大量的磁盤空間

3、GO Module介紹

為了解決GOPATH的問題,因此官方在1.11開始推出了Go Modules的功能。Go Modules解決方式很像是Java看到Maven的做法,將第三方庫儲存在本地的空間,並且給項目代碼去引用

3.1 設定GO111MODULE環境變量

總共可以設置三種不同的值

  • auto

默認值,go命令會根據當前目錄來決定是否啟用modules功能。需要滿足兩種情形:
該目錄不在GOPATH/src/
當前或上一層目錄存在go.mod文件

  • on

go命令會使用modules,而不會去GOPATH目錄下查找。

  • off

go命令將不會支持module功能,尋找依賴按照以前GOPATH的做法去尋找

目前1.16版本默認將這個參數設置成on,而且可能之后的版本會棄用掉GO111MODULE,因此建議要開發Go項目時就不再使用GOPATH了,而是采用Go Modules的做法,因此建議都設定為on

采用Go Modules,下載下來的第三方依賴就位於GOPATH/pkg/mod目錄下

3.2 初始化mod

go mod init <module name>

<module name>可填可不填,不填的話預設就是默認的文件名稱go.mod

在此文件中可以寫以下幾個關鍵字:

  • module

定義模組路徑

  • go

定義go語言version

  • require

指定依賴,預設是最新版,可以指定版本號

  • exclude

排除該依賴和其版本

  • replace

使用不同的依賴版本並替換原有的依賴版本注解
indirect代表被間接導入的依賴包

假設現在我要引入GitHub上的gin-gonic/gin的依賴,如下定義:

module myProject
go 1.16
require github.com/gin-gonic/gin v1.6.3

再執行以下指令:

go mod xxx

會將需要的依賴安裝在GOPATH/pkg/mod目錄里面

gin@v1.4.0 gin@v1.6.3 gin@v1.7.1

除了go.mod之外,go命令還維護一個名為go.sum的文件,其中包含特定模塊版本內容的預期加密哈希
go命令使用go.sum文件確保這些模塊的未來下載檢索與第一次下載相同,以確保項目所依賴的模塊不會出現意外更改,無論是出於惡意、意外還是其他原因。 go.modgo.sum都應檢入版本控制。
go.sum不需要手工維護,所以可以不用太關注

只要有開啟go modules功能,go get 就不會像以前一樣在GOPATH/src下放置依賴,而是會放在GOPATH/pkg/mod里面,並且go.mod會寫好引入

3.3 go mod命令

常用

go mod init:初始化go mod, 生成go.mod文件,后可接參數指定 module 名,上面已經演示過。
go mod download:手動觸發下載依賴包到本地cache(默認為$GOPATH/pkg/mod目錄)
go list -m -json all:以 json 的方式打印依賴詳情

其他

go mod graph: 打印項目的模塊依賴結構
go mod tidy :添加缺少的包,且刪除無用的包
go mod verify :校驗模塊是否被篡改過
go mod why: 查看為什么需要依賴
go mod vendor :導出項目所有依賴到vendor下
go mod edit :編輯go.mod文件

4、總結

GoPath所引出的問題,就是因為第三方類庫的包所導致的,所以在有了GoModule之后,GoPathGoModule就分別負責不同的職責,共同為Golang項目服務

GoPath用來存放我們從網上拉取的第三方依賴包
GoModule用來存放我們自己的Golang項目文件,當自己的項目需要依賴第三方的包的時候,我們通過GoModule目錄下的一個go.mod文件來引用GoPath目錄pkg包下的mod文件夾下的第三方依賴即可

這樣以來,既解決了原來只能局限在GoPath目錄src包下進行編程的問題,也解決了第三方依賴包難以管理和重復依賴占用磁盤空間的問題


免責聲明!

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



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