參考連接:https://blog.csdn.net/weixin_39003229/article/details/97638573git
Go.mod是Golang1.11版本新引入的官方包管理工具用於解決以前沒有地方記錄依賴包具體版本的問題,方便依賴包的管理。github
Modules是相關Go包的集合,是源代碼交換和版本控制的單元。go命令直接支持使用Modules,包括記錄和解析對其餘模塊的依賴性。Modules替換舊的基於GOPATH的方法,來指定使用哪些源文件。golang
Modules和傳統的GOPATH不一樣,不須要包含例如src,bin這樣的子目錄,一個源代碼目錄甚至是空目錄均可以做爲Modules,只要其中包含有go.mod文件。工具
如何使用go.mod?
1 首先將go的版本升級爲1.11以上ui
2 設置GO111MODULE加密
GO111MODULE
GO111MODULE有三個值:off, on和auto(默認值)。 GO111MODULE=off,go命令行將不會支持module功能,尋找依賴包的方式將會沿用舊版本那種經過vendor目錄或者GOPATH模式來查找。 GO111MODULE=on,go命令行會使用modules,而一點也不會去GOPATH目錄下查找。 GO111MODULE=auto,默認值,go命令行將會根據當前目錄來決定是否啓用module功能。這種狀況下能夠分爲兩種情形: 當前目錄在GOPATH/src以外且該目錄包含go.mod文件 當前文件在包含go.mod文件的目錄下面。
使用以前咱們要進行前期的準備,設置go的環境配置spa
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct.net
1.首先咱們要在GOPATH/src 目錄以外新建工程,或將老工程copy到GOPATH/src 目錄以外。命令行
PS:go.mod文件一旦建立後,它的內容將會被go toolchain全面掌控。go toolchain會在各種命令執行時,好比go get、go build、go mod等修改和維護go.mod文件。版本控制
1 module語句指定包的名字(路徑)
2 require語句指定的依賴項模塊
3 replace語句能夠替換依賴項模塊
4 exclude語句能夠忽略依賴項模塊
下面是咱們創建了一個hello.go的文件
package main import ( "fmt" ) func main() { fmt.Println("Hello, world!") }
2.在當前目錄下,命令行運行 go mod init + 模塊名稱 初始化模塊
go mod init hello
運行完以後,會在當前目錄下生成一個go.mod文件,這是一個關鍵文件,以後的包的管理都是經過這個文件管理。
官方說明:除了go.mod以外,go命令還維護一個名爲go.sum的文件,其中包含特定模塊版本內容的預期加密哈希
go命令使用go.sum文件確保這些模塊的將來下載檢索與第一次下載相同的位,以確保項目所依賴的模塊不會出現意外更改,不管是出於惡意、意外仍是其餘緣由。 go.mod和go.sum都應檢入版本控制。
go.sum 不須要手工維護,因此能夠不用太關注。
注意:子目錄裏是不須要init的,全部的子目錄裏的依賴都會組織在根目錄的go.mod文件裏
接下來,讓咱們的項目依稀一下第三方包
如修改hello.go文件以下,按照過去的作法,要運行hello.go須要執行go get 命令 下載gorose包到 $GOPATH/src
package main import ( "fmt" "github.com/gohouse/gorose" ) func main() { fmt.Println("Hello, world!") }
可是,使用了新的包管理就不在須要這樣作了
go run hello.go
稍等片刻… go 會自動查找代碼中的包,下載依賴包,而且把具體的依賴關係和版本寫入到go.mod和go.sum文件中。
查看go.mod,它會變成這樣:
module test require ( github.com/gohouse/gorose v1.0.5 )
require 關鍵字是引用,後面是包,最後v1.11.1 是引用的版本號
這樣,一個使用Go包管理方式建立項目的小例子就完成了。
問題一:依賴的包下載到哪裏了?還在GOPATH裏嗎?
不在。
使用Go的包管理方式,依賴的第三方包被下載到了$GOPATH/pkg/mod路徑下。
問題二: 依賴包的版本是怎麼控制的?
在上一個問題裏,能夠看到最終下載在GOPATH/pkg/mod裏能夠保存相同包的不一樣版本。
版本是在go.mod中指定的。若是,在go.mod中沒有指定,go命令會自動下載代碼中的依賴的最新版本,本例就是自動下載最新的版本。若是,在go.mod用require語句指定包和版本 ,go命令會根據指定的路徑和版本下載包,
指定版本時能夠用latest,這樣它會自動下載指定包的最新版本;
問題三: 能夠把項目放在$GOPATH/src下嗎?
能夠。可是go會根據GO111MODULE的值而採起不一樣的處理方式,默認狀況下,GO111MODULE=auto 自動模式
1.auto 自動模式下,項目在GOPATH/src的依賴包,在$GOPATH/src外,就使用go.mod 裏 require的包
2.on 開啓模式,1.12後,不管在$GOPATH/src裏仍是在外面,都會使用go.mod 裏 require的包
3.off 關閉模式,就是老規矩。
問題三: 依賴包中的地址失效了怎麼辦?好比 golang.org/x/… 下的包都沒法下載怎麼辦?
在go快速發展的過程當中,有一些依賴包地址變動了。之前的作法:
1.修改源碼,用新路徑替換import的地址
2.git clone 或 go get 新包後,copy到$GOPATH/src裏舊的路徑下
不管什麼方法,都不便於維護,特別是多人協同開發時。
使用go.mod就簡單了,在go.mod文件裏用 replace 替換包,例如
replace golang.org/x/text => github.com/golang/text latest
這樣,go會用 github.com/golang/text 替代golang.org/x/text,原理就是下載github.com/golang/text 的最新版本到 $GOPATH/pkg/mod/golang.org/x/text下。
問題四: init生成的go.mod的模塊名稱有什麼用?
本例裏,用 go mod init hello 生成的go.mod文件裏的第一行會申明module hello
由於咱們的項目已經不在$GOPATH/src裏了,那麼引用本身怎麼辦?就用模塊名+路徑。
例如,在項目下新建目錄 utils,建立一個tools.go文件:
package utils import 「fmt」 func PrintText(text string) { fmt.Println(text) }
在根目錄下的hello.go文件就能夠 import 「hello/utils」 引用utils
package main import ( "hello/utils" "github.com/astaxie/beego" ) func main() { utils.PrintText("Hi") beego.Run() }