偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

我們一起 Go Modules知識點(diǎn),你學(xué)會了嗎?

開發(fā) 前端
現(xiàn)在大小公司的項(xiàng)目應(yīng)該都已經(jīng)在使用Go Modules?進(jìn)行依賴包管理了,雖然Go Modules?相比于Maven、npm還不是很完善,但也在不斷地進(jìn)行優(yōu)化,變得越來越好,如果你現(xiàn)在項(xiàng)目還沒有使用go modules,可以準(zhǔn)備將項(xiàng)目遷移到go mod了,推薦你使用。

Go Modules發(fā)展史

go get階段

起初Go語言在1.5之前沒有依賴管理工具,若想引入依賴庫,需要執(zhí)行g(shù)o get命令將代碼拉取放入GOPATH/src目錄下,作為GOPATH下的全局依賴,這也就意味著沒有版本控制及隔離項(xiàng)目的包依賴;

vendor階段

為了解決隔離項(xiàng)目的包依賴問題,Go1.5版本推出了vendor機(jī)制,環(huán)境變量中有一個GO15VENDOREXPERIMENT需要設(shè)置為1,該環(huán)境變量在Go1.6版本時變成默認(rèn)開啟,目前已經(jīng)退出了歷史舞臺;

vendor其實(shí)就是將原來放在GOPATH/src的依賴包放到工程的vendor目錄中進(jìn)行管理,不同工程獨(dú)立地管理自己的依賴包,相互之間互不影響,原來是包共享的模式,通過vendor這種機(jī)制進(jìn)行隔離,在項(xiàng)目編譯的時候會先去vendor目錄查找依賴,如果沒有找到才會再去GOPATH目錄下查找;

優(yōu)點(diǎn):保證了功能項(xiàng)目的完整性,減少了下載依賴包,直接使用vendor就可以編譯

缺點(diǎn):仍然沒有解決版本控制問題,go get仍然是拉取最新版本代碼;

社區(qū)管理工具

很多優(yōu)秀的開發(fā)者在這期間也都實(shí)現(xiàn)了不錯的包依賴管理工具,例如:

godep:https://github.com/tools/godep

govendor:https://github.com/kardianos/govendor

glide:https://github.com/Masterminds/glide

dep:https://github.com/golang/dep

dep應(yīng)該是其中最成功的,得到了Go語言官方的支持,該項(xiàng)目也被放到了https://github.com/golang/dep,但是為什么dep沒有稱為官宣的依賴工具呢?

其實(shí)因?yàn)殡S著Russ Cox 與 Go 團(tuán)隊(duì)中的其他成員不斷深入地討論,發(fā)現(xiàn) dep 的一些細(xì)節(jié)似乎越來越不適合 Go,因此官方采取了另起 proposal 的方式來推進(jìn),其方案的結(jié)果一開始先是釋出 vgo,最終演變?yōu)槲覀儸F(xiàn)在所見到的 Go modules;

go modules

go modules是Russ Cox推出來的,發(fā)布于Go1.11,成長于Go1.12,豐富于Go1.13,正式于Go1.14推薦在生產(chǎn)上使用,幾乎后續(xù)的每個版本都或多或少的有一些優(yōu)化,在Go1.16引入go mod retract、在Go1.18引入go work工作區(qū)的概念,這些我們在本文都會介紹到;

Go Modules知識點(diǎn)

GO111MODULE環(huán)境變量

這個環(huán)境變量是Go Modules的開關(guān),主要有以下參數(shù):

  • auto:只在項(xiàng)目包含了go.mod文件時啟動go modules,在Go1.13版本中是默認(rèn)值
  • on:無腦啟動Go Modules,推薦設(shè)置,Go1.14版本以后的默認(rèn)值
  • off:禁用Go Modules,一般沒有使用go modules的工程使用;

我現(xiàn)在使用的Go版本是1.19.3,默認(rèn)GO111MODULE=on,感覺該變量也會像GO15VENDOREXPERIMENT最終推出系統(tǒng)環(huán)境變量的舞臺;

GOPROXY

該環(huán)境變量用于設(shè)置Go模塊代理,Go后續(xù)在拉取模塊版本時能夠脫離傳統(tǒng)的VCS方式從鏡像站點(diǎn)快速拉取,GOPROXY的值要以英文逗號分割,默認(rèn)值是https://proxy.golang.org,direct,但是該地址在國內(nèi)無法訪問,所以可以使用goproxy.cn來代替(七牛云配置),設(shè)置命令:

go env -w GOPROXY=GOPROXY=https://goproxy.cn,direct

也可以使用其他配置,例如阿里配置:

go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/

該環(huán)境變量也可以關(guān)閉,可以設(shè)置為"off",禁止Go在后續(xù)操作中使用任何Go module proxy;

上面的配置中我們用逗號分割后面的值是direct,它是什么意思呢?

direct為特殊指示符,因?yàn)槲覀冎付绥R像地址,默認(rèn)是從鏡像站點(diǎn)拉取,但是有些庫可能不存在鏡像站點(diǎn)中,direct可以指示Go回源到模塊版本的源地址去抓取,比如github,當(dāng)go module proxy返回404、410這類錯誤時,其會自動嘗試列表中的下一個,遇見direct時回源地址抓?。?/p>

GOSUMDB

該環(huán)境變量的值是一個Go checksum database,用于保證Go在拉取模塊版本時拉取到的模塊版本數(shù)據(jù)未經(jīng)篡改,若發(fā)現(xiàn)不一致會中止,也可以將值設(shè)置為??off??即可以禁止Go在后續(xù)操作中校驗(yàn)?zāi)K版本;

什么是Go checksum database?

Go checksum database主要用于保護(hù)Go不會從任何拉到被篡改過的非法Go模塊版本,詳細(xì)算法機(jī)制可以看一下:https://go.googlesource.com/proposal/+/master/design/25530-sumdb.md#proxying-a-checksum-database

GOSUMDB的默認(rèn)值是sum.golang.org,默認(rèn)值與自定義值的格式不一樣,默認(rèn)值在國內(nèi)是無法訪問,這個值我們一般不用動,因?yàn)槲覀円话阋呀?jīng)設(shè)置好了GOPROXY,goproxy.cn支持代理sum.golang.org;

GOSUMDB的值自定義格式如下:

  • 格式 1:<SUMDB_NAME>+<PUBLIC_KEY>。
  • 格式 2:<SUMDB_NAME>+<PUBLIC_KEY> <SUMDB_URL>。

GONOPROXY/GONOSUMDB/GOPRIVATE

這三個環(huán)境變量放在一起說,一般在項(xiàng)目中不經(jīng)常使用,這三個環(huán)境變量主要用于私有模塊的拉取,在GOPROXY、GOSUMDB中無法訪問到模塊的場景中,例如拉取git上的私有倉庫;

GONOPROXY、GONOSUMDB的默認(rèn)值是GOPRIVATE的值,所以我們一般直接使用GOPRIVATE即可,其值也是可以設(shè)置多個,以英文逗號進(jìn)行分割;例如:

$ go env -w GOPRIVATE="github.com/asong2020/go-localcache,git.xxxx.com"

也可以使用通配符的方式進(jìn)行設(shè)置,對域名設(shè)置通配符號,這樣子域名就都不經(jīng)過Go module proxy和Go checksum database;

全局緩存

go mod download會將依賴緩存到本地,緩存的目錄是GOPATH/pkg/mod/cache、GOPATH/pkg/sum,這些緩存依賴可以被多個項(xiàng)目使用,未來可能會遷移到$GOCACHE下面;

可以使用go clean -modcache清理所有已緩存的模塊版本數(shù)據(jù);

Go Modules命令

我們可以使用go help mod查看可以使用的命令:

go help mod
Go mod provides access to operations on modules.

Note that support for modules is built into all the go commands,
not just 'go mod'. For example, day-to-day adding, removing, upgrading,
and downgrading of dependencies should be done using 'go get'.
See 'go help modules' for an overview of module functionality.

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

Use "go help mod <command>" for more information about a command.

命令

作用

go mod init

生成go.mod文件

go mod download

下載go.mod文件中指明的所有依賴放到全局緩存

go mod tidy

整理現(xiàn)有的依賴,添加缺失或移除不使用的modules

go mod graph

查看現(xiàn)有的依賴結(jié)構(gòu)

go mod edit

編輯go.mod文件

go mod vendor

導(dǎo)出項(xiàng)目所有的依賴到vendor目錄

go mod verify

校驗(yàn)一個模塊是否被篡改過

go mod why

解釋為什么需要依賴某個模塊

go.mod文件

go.mod是啟用Go modules的項(xiàng)目所必須且最重要的文件,其描述了當(dāng)前項(xiàng)目的元信息,每個go.mod文件開頭符合包含如下信息:

module:用于定義當(dāng)前項(xiàng)目的模塊路徑(突破$GOPATH路徑)

go:當(dāng)前項(xiàng)目Go版本,目前只是標(biāo)識作用

require:用設(shè)置一個特定的模塊版本

exclude:用于從使用中排除一個特定的模塊版本

replace:用于將一個模塊版本替換為另外一個模塊版本,例如chromedp使用golang.org/x/image這個package一般直連是獲取不了的,但是它有一個github.com/golang/image的鏡像,所以我們要用replace來用鏡像替換它

restract:用來聲明該第三方模塊的某些發(fā)行版本不能被其他模塊使用,在Go1.16引入

例子:

圖片

接下來我們分模塊詳細(xì)介紹一下各部分;

module path

go.mod文件的第一行是module path,采用倉庫+module name的方式定義,例如上面的項(xiàng)目:

module github.com/asong2020/go-localcache

因?yàn)镚o module遵循語義化版本規(guī)范2.0.0,所以如果工程的版本已經(jīng)大于2.0.0,按照規(guī)范需要加上major的后綴,module path改成如下:

module github.com/asong2020/go-localcache/v2
module github.com/asong2020/go-localcache/v3
......

go version

go.mod文件的第二行是go version,其是用來指定你的代碼所需要的最低版本:

go 1.19.3

其實(shí)這一行不是必須的,目前也只是標(biāo)識作用,可以不寫;

require

require用來指定該項(xiàng)目所需要的各個依賴庫以及他們的版本,從上面的例子中我們看到版本部分有不同的寫法,還有注釋,接下來我們來解釋一下這部分;

indirect注釋
github.com/davecgh/go-spew v1.1.0 // indirect

以下場景才會添加indirect注釋:

  • 當(dāng)前項(xiàng)目依賴包A,但是A依賴包B,但是A的go.mod文件中缺失B,所以在當(dāng)前項(xiàng)目go.mod中補(bǔ)充B并添加indirect注釋
  • 當(dāng)前項(xiàng)目依賴包A,但是依賴包A沒有g(shù)o.mod文件,所以在當(dāng)前項(xiàng)目go.mod中補(bǔ)充B并添加indirect注釋
  • 當(dāng)前項(xiàng)目依賴包A,依賴包A又依賴包B,當(dāng)依賴包A降級不在依賴B時,這個時候就會標(biāo)記indirect注釋,可以執(zhí)行g(shù)o mod tidy移除該依賴;

Go1.17版本對此做了優(yōu)化,indirect 的 module 將被放在單獨(dú) require 塊的,這樣看起來更加清晰明了。

incompatible標(biāo)記

我們在項(xiàng)目中會看到有一些庫后面添加了incompatible標(biāo)記:

github.com/dgrijalva/jwt-go v3.2.0+incompatible

jwt-go這個庫就是這樣的,這是因?yàn)閖wt-go的版本已經(jīng)大于2了,但是他們的module path仍然沒有添加v2、v3這樣的后綴,不符合Go的module管理規(guī)范,所以go module把他們標(biāo)記為incompatible,不影響引用;

版本號

go module拉取依賴包本質(zhì)也是go get行為,go get主要提供了以下命令:

命令

作用

go get

拉取依賴,會進(jìn)行指定性拉?。ǜ拢?,并不會更新所依賴的其它模塊。

go get -u

更新現(xiàn)有的依賴,會強(qiáng)制更新它所依賴的其它全部模塊,不包括自身。

go get -u -t ./...

更新所有直接依賴和間接依賴的模塊版本,包括單元測試中用到的。

go get拉取依賴包取決于依賴包是否有發(fā)布的tags:

  1. 拉取的依賴包沒有發(fā)布tags
  • 默認(rèn)取主分支最近一次的commit的commit hash,生成一個偽版本號
  1. 拉取的依賴包有發(fā)布tags
  • 如果只有單個模塊,那么就取主版本號最大的那個tag

  • 如果有多個模塊,則推算相應(yīng)的模塊路徑,取主版本號最大的那個tag

沒有發(fā)布的tags:

github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751

v0.0.0:根據(jù)commit的base version生成的:

  • 如果沒有base version,那么就是vx.0.0的形式
  • 如果base version是一個預(yù)發(fā)版本,那么就是vx.y.z-pre.0的形式
  • 如果base version是一個正式發(fā)布的版本,那么它就patch號加1,就是vx.y.(z+1)-0的形式

?20190718012654:是這次提交的時間,格式是??yyyyMMddhhmmss??

fb15b899a751:是這個版本的commit id,通過這個可以確定這個庫的特定的版本

github.com/beego/bee v1.12.0

replace

replace用于解決一些錯誤的依賴庫的引用或者調(diào)試依賴庫;

場景舉例:

舉例1:

日常開發(fā)離不開第三方庫,大部分場景都可以滿足我們的需要,但是有些時候我們需要對依賴庫做一些定制修改,依賴庫修改后,我們想引起最小的改動,就可以使用replace命令進(jìn)行重新引用,調(diào)試也可以使用replace進(jìn)行替換,Go1.18引入了工作區(qū)的概念,調(diào)試可以使用work進(jìn)行代替,后面會介紹;

舉例2:

golang.org/x/crypto庫一般我們下載不下來,可以使用replace引用到github.com/golang/crypto:

go mod edit -replace golang.org/x/crypto=github.com/golang/crypto@v0.0.0-20160511215533-1f3b11f56072

exclude

用于跳過某個依賴庫的版本,使用場景一般是我們知道某個版本有bug或者不兼容,為了安全起可以使用exclude跳過此版本;

exclude (
go.etcd.io/etcd/client/v2 v2.305.0-rc.0
)

retract

這個特性是在Go1.16版本中引入,用來聲明該第三方模塊的某些發(fā)行版本不能被其他模塊使用;

使用場景:發(fā)生嚴(yán)重問題或者無意發(fā)布某些版本后,模塊的維護(hù)者可以撤回該版本,支持撤回單個或多個版本;

這種場景以前的解決辦法:

維護(hù)者刪除有問題版本的tag,重新打一個新版本的tag;

使用者發(fā)現(xiàn)有問題的版本tag丟失,手動介入升級,并且不明真因;

引入retract后,維護(hù)者可以使用retract在go.mod中添加有問題的版本:

// 嚴(yán)重bug...
retract (
v0.1.0
v0.2.0
)

重新發(fā)布新版本后,在引用該依賴庫的使用執(zhí)行g(shù)o list可以看到 版本和"嚴(yán)重bug..."的提醒;

該特性的主要目的是將問題更直觀的反饋到開發(fā)者的手中;

go.sum文件

go.sun文件也是在go mod init階段創(chuàng)建,go.sum的介紹文檔偏少,我們一般也很少關(guān)注go.sum文件,go.sum主要是記錄了所有依賴的module的校驗(yàn)信息,內(nèi)容如下:

圖片

image-20230102193717816

從上面我們可以看到主要是有兩種形式:

  • h1:
  • /go.mod h1:

其中module是依賴的路徑,version是依賴的版本號。hash是以??h1:??開頭的字符串,hash 是 Go modules 將目標(biāo)模塊版本的 zip 文件開包后,針對所有包內(nèi)文件依次進(jìn)行 hash,然后再把它們的 hash 結(jié)果按照固定格式和算法組成總的 hash 值。

h1 hash 和 go.mod hash兩者要不同時存在,要不就是只存在go.mod hash,當(dāng)Go認(rèn)為肯定用不到某個版本的時候就會省略它的h1 hash,就只有g(shù)o.mod hash;

Go Modules在項(xiàng)目中使用

使用go modules的一個前置條件是Go語言版本大于等于Go1.11;

然后我們要檢查環(huán)境變量GO111MODULE是否開啟,執(zhí)行g(shù)o env查看:

$ go env
GO111MODULE=off

執(zhí)行如下命令打開go mod:

$ go env -w GO111MODULE=on

接下來我們隨意創(chuàng)建一個項(xiàng)目:

$ mkdir -p asong/demo
$ cd asong/demo

執(zhí)行g(shù)o mod init初始化該項(xiàng)目:

$ go mod init github.com/asong/demo
go: creating new go.mod: module github.com/asong/demo

接下來我們在demo目錄下創(chuàng)建main.go文件,寫下如下代碼:

package main

import (
"fmt"
cache "github.com/asong2020/go-localcache"
)

func main() {
c, err := cache.NewCache()
if err != nil {
return
}
key := "asong"
value := []byte("公眾號:Golang夢工廠")
err = c.Set(key, value)
if err != nil {
return
}
entry, err := c.Get(key)
if err != nil {
return
}
fmt.Printf("get value is %s\n", string(entry))

err = c.Delete(key)
if err != nil {
return
}
}

然后執(zhí)行g(shù)o mod tidy命令:

圖片

自動根據(jù)main.go文件更新依賴,我們再看一下go.mod文件:

圖片

以上就是在項(xiàng)目對go.mod的簡單使用;

go1.18新特性:工作區(qū)

工作區(qū)用來解決什么問題?

場景1:我們有時在本地會對一些三方依賴庫進(jìn)行特制修改,然后想在項(xiàng)目修改依賴庫引用到本地進(jìn)行調(diào)試,這時我們可以使用replace做替換,這樣就可以在本地進(jìn)行開發(fā)聯(lián)調(diào),這樣雖然可以解決問題,但是會存在問題,因?yàn)槭窃陧?xiàng)目的go.mod文件直接修改的,如果誤傳到遠(yuǎn)程倉庫,會影響到其他開發(fā)同學(xué);

場景2:我們在本地開發(fā)了一些依賴庫,這時想在本地測試一下,還未發(fā)到遠(yuǎn)程倉庫,那么我們在其他項(xiàng)目中引入該依賴庫后,執(zhí)行??go mod tidy??就會報遠(yuǎn)程庫沒有找到的問題,所以就必須要把依賴庫先推送到遠(yuǎn)程,在引用調(diào)試;

正是這些問題,Go語言在Go1.18正式增加了go work工作區(qū)的概念,其實(shí)就是將N個Go Module組成一個Go Work,工作區(qū)的讀取優(yōu)先級是最高的,執(zhí)行g(shù)o help work可以查看go work提供的功能:

$ go help work
Usage:

go work <command> [arguments]

The commands are:

edit edit go.work from tools or scripts
init initialize workspace file
sync sync workspace build list to modules
use add modules to workspace file

Use "go help work <command>" for more information about a command.

執(zhí)行g(shù)o work init命令初始化一個新的工作區(qū),在項(xiàng)目中生成一個go.work文件:

go 1.18
// 多模塊添加
use (...)

replace XXXXX => XXXX v1.4.5

go.work文件與go.mod文件語法一致,go.work支持三個指令:

  • go:聲明go版本號
  • use:聲明應(yīng)用所依賴模塊的具體文件路徑,路徑可以是絕對路徑或相對路徑,即使路徑是當(dāng)前應(yīng)用目錄外也可
  • replace:聲明替換某個模塊依賴的導(dǎo)入路徑,優(yōu)先級高于 go.mod 中的 replace 指令;

所以針對上述場景,我們使用go work init命令在項(xiàng)目中對本地依賴庫進(jìn)行關(guān)聯(lián)即可解決,后續(xù)我們只需要在git配置文件中添加go.work文件不推送到遠(yuǎn)程即可;

我們也可以在編譯時通過-workfile=off指令禁用工作區(qū)模式:

$ go build -workfile=offf .

go.work的推出主要是用于在本地調(diào)試,不會因?yàn)樾薷膅o.mod引入問題;

參考文獻(xiàn)

  • Go1.18 新特性:多 Module 工作區(qū)模式
  • Go Modules 終極入門
  • Go mod 七宗罪
  • 深入Go Module之go.mod文件解析

總結(jié)

現(xiàn)在大小公司的項(xiàng)目應(yīng)該都已經(jīng)在使用Go Modules?進(jìn)行依賴包管理了,雖然Go Modules?相比于Maven、npm還不是很完善,但也在不斷地進(jìn)行優(yōu)化,變得越來越好,如果你現(xiàn)在項(xiàng)目還沒有使用go modules,可以準(zhǔn)備將項(xiàng)目遷移到go mod了,推薦你使用;

好啦,本文到這里就結(jié)束了,我是asong,我們下期見。

責(zé)任編輯:武曉燕 來源: Golang夢工廠
相關(guān)推薦

2023-11-13 18:36:04

知識抽取NER

2023-10-31 14:04:17

Rust類型編譯器

2023-06-07 14:07:00

架構(gòu)

2023-04-13 08:40:12

MySQL服務(wù)器SELECT

2021-12-14 09:34:31

丑數(shù)順序指針

2021-05-31 09:23:04

管道模式責(zé)任鏈

2025-01-06 09:26:49

2024-09-11 08:02:27

k8sgitlab升級

2022-12-22 08:14:54

2022-06-15 08:00:50

磁盤RedisRocketMQ

2022-01-17 07:50:37

Go代碼規(guī)范

2022-08-29 08:05:44

Go類型JSON

2023-03-07 07:50:15

Transactio事務(wù)代碼

2023-11-27 07:26:42

Springboot容器

2023-08-01 12:51:18

WebGPT機(jī)器學(xué)習(xí)模型

2024-01-02 12:05:26

Java并發(fā)編程

2024-01-19 08:25:38

死鎖Java通信

2024-02-04 00:00:00

Effect數(shù)據(jù)組件

2023-07-26 13:11:21

ChatGPT平臺工具

2023-01-10 08:43:15

定義DDD架構(gòu)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號