自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

我們一起 Go Modules知識點,你學會了嗎?

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

Go Modules發(fā)展史

go get階段

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

vendor階段

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

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

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

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

社區(qū)管理工具

很多優(yōu)秀的開發(fā)者在這期間也都實現(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應該是其中最成功的,得到了Go語言官方的支持,該項目也被放到了https://github.com/golang/dep,但是為什么dep沒有稱為官宣的依賴工具呢?

其實因為隨著Russ Cox 與 Go 團隊中的其他成員不斷深入地討論,發(fā)現(xiàn) dep 的一些細節(jié)似乎越來越不適合 Go,因此官方采取了另起 proposal 的方式來推進,其方案的結果一開始先是釋出 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知識點

GO111MODULE環(huán)境變量

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

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

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

GOPROXY

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

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

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

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

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

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

direct為特殊指示符,因為我們指定了鏡像地址,默認是從鏡像站點拉取,但是有些庫可能不存在鏡像站點中,direct可以指示Go回源到模塊版本的源地址去抓取,比如github,當go module proxy返回404、410這類錯誤時,其會自動嘗試列表中的下一個,遇見direct時回源地址抓??;

GOSUMDB

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

什么是Go checksum database?

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

GOSUMDB的默認值是sum.golang.org,默認值與自定義值的格式不一樣,默認值在國內是無法訪問,這個值我們一般不用動,因為我們一般已經(jīng)設置好了GOPROXY,goproxy.cn支持代理sum.golang.org;

GOSUMDB的值自定義格式如下:

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

GONOPROXY/GONOSUMDB/GOPRIVATE

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

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

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

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

全局緩存

go mod download會將依賴緩存到本地,緩存的目錄是GOPATH/pkg/mod/cache、GOPATH/pkg/sum,這些緩存依賴可以被多個項目使用,未來可能會遷移到$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)有的依賴結構

go mod edit

編輯go.mod文件

go mod vendor

導出項目所有的依賴到vendor目錄

go mod verify

校驗一個模塊是否被篡改過

go mod why

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

go.mod文件

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

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

go:當前項目Go版本,目前只是標識作用

require:用設置一個特定的模塊版本

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

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

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

例子:

圖片

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

module path

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

module github.com/asong2020/go-localcache

因為Go 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

其實這一行不是必須的,目前也只是標識作用,可以不寫;

require

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

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

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

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

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

incompatible標記

我們在項目中會看到有一些庫后面添加了incompatible標記:

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

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

版本號

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

命令

作用

go get

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

go get -u

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

go get -u -t ./...

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

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

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

  • 如果有多個模塊,則推算相應的模塊路徑,取主版本號最大的那個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是一個預發(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用于解決一些錯誤的依賴庫的引用或者調試依賴庫;

場景舉例:

舉例1:

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

舉例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ā)生嚴重問題或者無意發(fā)布某些版本后,模塊的維護者可以撤回該版本,支持撤回單個或多個版本;

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

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

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

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

// 嚴重bug...
retract (
v0.1.0
v0.2.0
)

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

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

go.sum文件

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

圖片

image-20230102193717816

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

  • h1:
  • /go.mod h1:

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

h1 hash 和 go.mod hash兩者要不同時存在,要不就是只存在go.mod hash,當Go認為肯定用不到某個版本的時候就會省略它的h1 hash,就只有go.mod hash;

Go Modules在項目中使用

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

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

$ go env
GO111MODULE=off

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

$ go env -w GO111MODULE=on

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

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

執(zhí)行go mod init初始化該項目:

$ 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í)行go mod tidy命令:

圖片

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

圖片

以上就是在項目對go.mod的簡單使用;

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

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

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

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

正是這些問題,Go語言在Go1.18正式增加了go work工作區(qū)的概念,其實就是將N個Go Module組成一個Go Work,工作區(qū)的讀取優(yōu)先級是最高的,執(zhí)行go 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í)行go work init命令初始化一個新的工作區(qū),在項目中生成一個go.work文件:

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

replace XXXXX => XXXX v1.4.5

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

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

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

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

$ go build -workfile=offf .

go.work的推出主要是用于在本地調試,不會因為修改go.mod引入問題;

參考文獻

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

總結

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

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

責任編輯:武曉燕 來源: Golang夢工廠
相關推薦

2023-11-13 18:36:04

知識抽取NER

2023-10-31 14:04:17

Rust類型編譯器

2023-06-07 14:07:00

架構

2023-04-13 08:40:12

MySQL服務器SELECT

2021-12-14 09:34:31

丑數(shù)順序指針

2021-05-31 09:23:04

管道模式責任鏈

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事務代碼

2023-11-27 07:26:42

Springboot容器

2021-11-26 07:00:05

反轉整數(shù)數(shù)字

2024-02-21 19:02:05

Go模板化方式

2024-03-18 08:06:59

JavaGo開發(fā)

2024-09-26 09:10:08

2024-01-02 12:05:26

Java并發(fā)編程

2023-08-01 12:51:18

WebGPT機器學習模型
點贊
收藏

51CTO技術棧公眾號