go?mod的使用方法小結(jié)
前言
對(duì)于多個(gè)項(xiàng)目來(lái)說(shuō),把所有的源碼都放在GOPATH下的src目錄下非常的不方便。golang給我們提供了一個(gè)叫go mod的命令來(lái)脫離src目錄,方便我們管理go項(xiàng)目。go mod 是go官方提供的go版本管理的一個(gè)方案,目前1.15已經(jīng)可用于生產(chǎn)環(huán)境。
1.go modules的基本介紹
1.1 提供的命令
在go環(huán)境的shell中執(zhí)行go mod help查看命令和說(shuō)明。
Usage:
go mod <command> [arguments]
The commands are:
download download modules to local cache
edit edit go.mod from tools or scripts
graph print module requirement graph
init initialize new module in current directory
tidy add missing and remove unused modules
vendor make vendored copy of dependencies
verify verify dependencies have expected content
why explain why packages or modules are needed
1.2 提供的環(huán)境變量
用go env查看go的環(huán)境變量,在所有g(shù)o提供的環(huán)境變量中,有一個(gè)是和go mod相關(guān)的。
GO111MODULE="on" GOPROXY="https://goproxy.cn,direct" GONOPROXY="git.example.com,x1" GONOSUMDB="git.example.com,x1" GOPATH="/home/go-project/" GOPRIVATE="git.example.com,x1" GOSUMDB="sum.golang.org" # 省略其余環(huán)境變量...
1.2.1 說(shuō)明
1) GO111MODULE
go語(yǔ)言提供GO111MODULE環(huán)境變量三個(gè)值,用于GO111MODULE的開(kāi)關(guān):
- auto:只要項(xiàng)目中包含了
go.mod這個(gè)文件,就啟動(dòng)該項(xiàng)目的go modules,在 Go1.11 至 Go1.14 中仍然是默認(rèn)值。 - on:啟動(dòng)
go modules - off:關(guān)閉
go modules
2) GOPROXY
go env中默認(rèn)的代理是GOPROXY="https://proxy.golang.org,direct",但是在國(guó)內(nèi)是無(wú)法訪問(wèn)的,這里需要設(shè)置成國(guó)內(nèi)的代理地址GOPROXY="https://goproxy.cn,direct"
GOPROXY的值是一個(gè)以英文逗號(hào) “,” 分割的 Go 模塊代理列表,允許設(shè)置多個(gè)模塊代理,假設(shè)你不想使用,也可以將其設(shè)置為 “off” ,這將會(huì)禁止 Go 在后續(xù)操作中使用任何 Go 模塊代理。
direct
實(shí)際上 “direct” 是一個(gè)特殊指示符,用于指示 Go 回源到模塊版本的源地址去抓取(比如 GitHub 等),場(chǎng)景如下:當(dāng)值列表中上一個(gè) Go 模塊代理返回 404 或 410 錯(cuò)誤時(shí),Go 自動(dòng)嘗試列表中的下一個(gè),遇見(jiàn) “direct” 時(shí)回源,也就是回到源地址去抓取,而遇見(jiàn) EOF 時(shí)終止并拋出類似 “invalid version: unknown revision…” 的錯(cuò)誤。
在cmd中執(zhí)行set GO111MODULE=on

3)GONOPROXY/GONOSUMDB/GOPRIVATE
這三個(gè)環(huán)境變量都是用在當(dāng)前項(xiàng)目依賴了私有模塊,例如像是你公司的私有 git 倉(cāng)庫(kù),又或是 github 中的私有庫(kù),都是屬于私有模塊,都是要進(jìn)行設(shè)置的,否則會(huì)拉取失敗。對(duì)于一些自己的私有模塊代碼,需要在GOPRIVATE上設(shè)置,在拉取時(shí)會(huì)提示輸入用戶名和密碼。
可以設(shè)置多個(gè),用英文的逗號(hào)分隔開(kāi);或者用通配符等
go env -w GOPRIVATE="git.example.com,github.com/eddycjy/mquote" go env -w GOPRIVATE="*.example.com" # 通配example.com的域名
2.go modules的基本使用
開(kāi)啟go modules后,就可以創(chuàng)建項(xiàng)目并且生成mod文件,來(lái)管理項(xiàng)目的所有依賴了。以下是go env環(huán)境的配置:
GO111MODULE="auto" GOARCH="amd64" GOBIN="/go/bin/" GOCACHE="/root/.cache/go-build" GOENV="/root/.config/go/env" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="linux" GOINSECURE="" GONOPROXY="" GONOSUMDB="" GOOS="linux" GOPATH="/home/go-project/" GOPRIVATE="" GOPROXY="https://goproxy.cn,direct" GOROOT="/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/go/pkg/tool/linux_amd64" GCCGO="gccgo" AR="ar" CC="gcc" CXX="g++" CGO_ENABLED="1" GOMOD="" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build940953411=/tmp/go-build -gno-record-gcc-switches"
設(shè)置了GOPATH為/home/go-project/,并且代理指向了國(guó)內(nèi)的代理地址,防止國(guó)外鏡像無(wú)法訪問(wèn)的情況。
2.1 初始化項(xiàng)目
在$GOPATH目錄下創(chuàng)建一個(gè)新的項(xiàng)目example.com/mycount/hello,example.com模擬github.com,mycount模擬賬號(hào),hello是最終的項(xiàng)目名稱。目錄和文件結(jié)構(gòu):

2.1.1 初始化.mod文件
在hello目錄下執(zhí)行go mod init example.com/mycount/hello初始化hello項(xiàng)目的mod文件,如下:

執(zhí)行完初始化操作后生成了一個(gè)go.mod的文件,里面只記錄了2行:

- module:用于定義當(dāng)前項(xiàng)目的模塊路徑
- go:用于標(biāo)識(shí)當(dāng)前模塊的 Go 語(yǔ)言版本,值為初始化模塊時(shí)的版本,目前來(lái)看還只是個(gè)標(biāo)識(shí)作用
2.1.2 簡(jiǎn)單一個(gè)示例
在hello目錄下寫(xiě)一個(gè)main.go的文件,里面用了一個(gè)第三方的庫(kù)。
package main
import (
"net/http"
"github.com/gin-gonic/gin"
"github.com/json-iterator/go"
)
type resp struct {
Status int `json:"status"`
Message string `json:"message"`
}
func main() {
router := gin.Default()
router.GET("/", hello())
if err := router.Run(":6060"); err != nil {
panic(err)
}
}
func hello() gin.HandlerFunc {
return func(context *gin.Context) {
strResp, _ := jsoniter.MarshalToString(resp{
Status: http.StatusOK,
Message: "success",
})
context.String(http.StatusOK, strResp)
}
}
在hello目錄下執(zhí)行go get命令,拉取依賴庫(kù):

拉取依賴之后生成了一個(gè)go.mod和go.sum文件,go.mod文件:

go.sum的內(nèi)容:

同時(shí)在$GOPATH目錄下多了一個(gè)pkg文件,里面有拉取的文件依賴。這個(gè)文件是一個(gè)全局的緩存,
2.1.3 go modules的go get
在拉取項(xiàng)目依賴時(shí),你會(huì)發(fā)現(xiàn)拉取的過(guò)程總共分為了三大步,分別是 finding(發(fā)現(xiàn))、downloading(下載)以及 extracting(提?。?, 并且在拉取信息上一共分為了三段內(nèi)容:

需要注意的是,所拉取版本的 commit 時(shí)間是以UTC時(shí)區(qū)為準(zhǔn),而并非本地時(shí)區(qū),同時(shí)我們會(huì)發(fā)現(xiàn)我們 go get 命令所拉取到的版本是 v0.0.0,這是因?yàn)槲覀兪侵苯訄?zhí)行 go get -u 獲取的,并沒(méi)有指定任何的版本信息,由 Go modules 自行按照內(nèi)部規(guī)則進(jìn)行選擇。

那么我想選擇具體版本應(yīng)當(dāng)如何執(zhí)行呢,如下:

3.使用go mod發(fā)布自己的包
3.1 發(fā)布公開(kāi)的包
公開(kāi)的發(fā)布包無(wú)需修改go env中的一些環(huán)境變量,默認(rèn)的環(huán)境變量即可。
3.1.1 包的實(shí)現(xiàn)
假設(shè)我們有一個(gè)模塊需要提供給第三方使用,并且這個(gè)包是發(fā)布在了gittee上,假設(shè)我在gitee上得賬號(hào)是gitee.com\luciferofwg。我們后期會(huì)根據(jù)迭代或者功能維護(hù)版本,每當(dāng)有更新或者升級(jí)的時(shí)候就發(fā)布最新的版本,版本遵循語(yǔ)義化版本定義。什么是語(yǔ)義化版本
這個(gè)包中包含一個(gè)函數(shù),用于打印一句話,如下所示:
// hello.go
package hello
import "fmt"
func SayHello() {
fmt.Println("hello world")
}
在GOPATH下新建目錄hello,在命令行下進(jìn)入hello目錄,執(zhí)行go mod init來(lái)生成go mod文件,如下:

生成的包名為gitee.com/luciferofwg/hello,后期在引用這個(gè)包時(shí)就import 這個(gè)包名。
將hello倉(cāng)庫(kù)提交到gitee上,完成發(fā)布包的第一個(gè)階段。
3.1.2 包的發(fā)布
經(jīng)過(guò)上一步驟,在倉(cāng)庫(kù)中就有了一個(gè)名為hello的公開(kāi)倉(cāng)庫(kù),如下:

假如我們認(rèn)為這個(gè)版本是穩(wěn)定可靠的,這時(shí)候我們需要發(fā)布一個(gè)可以使用的版本,gitee發(fā)布的流程如下:
點(diǎn)擊倉(cāng)庫(kù)中右側(cè)的創(chuàng)建按鈕,在彈出的頁(yè)面中創(chuàng)建發(fā)行版本號(hào),填寫(xiě)完畢后點(diǎn)擊創(chuàng)建發(fā)行版本完成發(fā)布。
圖1 創(chuàng)建發(fā)行版本

圖2 發(fā)行版本信息

圖3 已創(chuàng)建的發(fā)行版本

到此我們發(fā)行了一個(gè)版本為v1.0.4的版本。
3.1.3 包的使用
對(duì)于已經(jīng)發(fā)行的包,這里介紹如何使用它。首先定義一個(gè)名為test的包,因?yàn)閠est為調(diào)用的程序,因此我們初始化mod時(shí)直接按照程序的名字初始化,即:go mod test,完成初始化。如下:

在test目錄下編寫(xiě)如下代碼:
package main
import "gitee.com/luciferofwg/hello"
func main() {
hello.SayHello()
}
然后再命令行中執(zhí)行go mod tidy整理go mod,此時(shí)go mod會(huì)根據(jù)程序包的引用關(guān)系按照包名從互聯(lián)網(wǎng)上拉去對(duì)應(yīng)的包。執(zhí)行完成后go.mod如下:

運(yùn)行的結(jié)果:

需要注意的是:
默認(rèn)拉去的是最新的發(fā)布版本,如果想制定版本,只需要修改go.mod中require最后面的版本號(hào)即可。如何修改go.mod參考go help mod命令的edit項(xiàng)。
3.2 發(fā)布私有包
3.2.1 go env環(huán)境變量和git配置的修改
1.go env環(huán)境變量的修改
私有包和公開(kāi)包的區(qū)別最大的區(qū)別是權(quán)限的和git拉去包的過(guò)程,這時(shí)候需要對(duì)go env中的一些參數(shù)修改。涉及到的一些參數(shù)GOINSECURE,GONOPROXY,GONOSUMDB,含義:GOINSECURE:如果代碼倉(cāng)庫(kù)是自己搭建的,沒(méi)有“合法”的證書(shū),則需要配置這個(gè)信息GONOPROXY:在這個(gè)變量中配置的域名或者倉(cāng)庫(kù)地址不會(huì)走代理(我們?cè)谇懊嬖O(shè)置了cn的代理)GONOSUMDB:1.15后會(huì)對(duì)包進(jìn)行校驗(yàn),此處的配置和GONOPROXY的含義一樣
看一下我們的go env變量,之前已經(jīng)修改過(guò)了,內(nèi)容如下:

注:
windows下修改時(shí)直接將上述的配置增加系統(tǒng)的環(huán)境變量即可,linux下在bash的配置文件中修改(具體修改可以自行搜索)。
2.git配置的修改
由于是私有的包,拉去時(shí)需要獲取拉去的權(quán)限,默認(rèn)的https或者h(yuǎn)ttp的方式需要密碼。如果我們本地已經(jīng)配置了對(duì)應(yīng)的gitee上的私鑰,且已經(jīng)在gitee對(duì)應(yīng)的賬戶上配置了權(quán)限,那么我們就可以通過(guò)git@xxx的方式訪問(wèn)私有的倉(cāng)庫(kù)。
打開(kāi)本地git的配置,windows下是c:\\user\\用戶名\\.bashconfig文件,打開(kāi)這個(gè)文件。增加以下代碼:
[url "git@gitee.com:"]insteadof = https://gitee.com
表示訪問(wèn)https://gitee.com的過(guò)程替換為git@gitee.com:,即通過(guò)bash就可以訪問(wèn)私有庫(kù)了。
3.2.2 私有包的實(shí)現(xiàn)
1.私有包實(shí)現(xiàn)
我們創(chuàng)建一個(gè)私有的倉(cāng)庫(kù),名為hi,包含一個(gè)函數(shù)SayHello,打印hello world。
同樣的,創(chuàng)建go.mod,實(shí)現(xiàn)SayHello函數(shù),推送到gitee。
圖1 私有倉(cāng)庫(kù)hi

2.函數(shù)和源碼
// hi包的SayHello函數(shù)
package hi
import "fmt"
func SayHello() {
fmt.Println("hi, world")
}
hi包的go.mod

3.2.3 私有包的發(fā)布
根據(jù)上述的源碼,使用同樣的方式發(fā)布版本。
圖1 發(fā)布的版本1.0.0

3.2.4 私有包的引用
如果已經(jīng)配置了go env的參數(shù)和git配置,使用的過(guò)程和公開(kāi)包的使用是一樣的。基于原來(lái)的版本,增加了一個(gè)hi包的函數(shù)引用和導(dǎo)入,在test目錄下執(zhí)行go mod tidy,就會(huì)自動(dòng)拉取發(fā)布的包了。
package main
import (
"gitee.com/luciferofwg/hello"
"gitee.com/luciferofwg/hi"
)
func main() {
hello.SayHello()
hi.SayHello()
}
test程序的go.mod如下:

到此這篇關(guān)于go mod的使用方法小結(jié)的文章就介紹到這了,更多相關(guān)go mod使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語(yǔ)言中make和new函數(shù)的用法與區(qū)別
這篇文章介紹了Go語(yǔ)言中make和new函數(shù)的用法與區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-07-07
通過(guò)手機(jī)案例理解Go設(shè)計(jì)模式之裝飾器模式的功能屬性
這篇文章主要為大家介紹了Go設(shè)計(jì)模式之裝飾器模式的功能屬性,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
Go項(xiàng)目編寫(xiě)Makefile規(guī)則文件概述
這篇文章主要為大家介紹了Go項(xiàng)目編寫(xiě)Makefile文件規(guī)則概述,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04
go實(shí)現(xiàn)thrift的網(wǎng)絡(luò)傳輸性能及需要注意問(wèn)題示例解析
這篇文章主要為大家介紹了go實(shí)現(xiàn)thrift的網(wǎng)絡(luò)傳輸性能及需要注意問(wèn)題示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
Go語(yǔ)言TCP從原理到代碼實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了Go語(yǔ)言TCP從原理到代碼實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
GoLang RabbitMQ TTL與死信隊(duì)列以及延遲隊(duì)列詳細(xì)講解
這篇文章主要介紹了GoLang RabbitMQ TTL與死信隊(duì)列以及延遲隊(duì)列,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-12-12
Golang新提案:panic?能不能加個(gè)?PanicError?
這篇文章主要為大家介紹了Golang的新提案關(guān)于panic能不能加個(gè)PanicError的問(wèn)題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
利用Go語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單Ping過(guò)程的方法
相信利用各種語(yǔ)言實(shí)現(xiàn)Ping已經(jīng)是大家喜聞樂(lè)見(jiàn)的事情了,網(wǎng)絡(luò)上利用Golang實(shí)現(xiàn)Ping已經(jīng)有比較詳細(xì)的代碼示例,但大多是僅僅是實(shí)現(xiàn)了Request過(guò)程,而對(duì)Response的回顯內(nèi)容并沒(méi)有做接收。而Ping程序不僅僅是發(fā)送一個(gè)ICMP,更重要的是如何接收并進(jìn)行統(tǒng)計(jì)。2016-09-09
詳解Go中g(shù)in框架如何實(shí)現(xiàn)帶顏色日志
當(dāng)我們?cè)诮K端上(比如Goland)運(yùn)行g(shù)in框架搭建的服務(wù)時(shí),會(huì)發(fā)現(xiàn)輸出的日志是可以帶顏色的,那這是如何實(shí)現(xiàn)的呢?本文就來(lái)和大家簡(jiǎn)單講講2023-04-04

