我的名字叫浩仔/Go Modules 梳理

Created Mon, 08 May 2023 14:21:52 +0800 Modified Thu, 11 May 2023 11:31:53 +0800
3038 Words

大致梳理这几部分:更新历程,大致规则,命令解释,实践操作

Mod展示

x
+
~(~zsh):
  • ➜  ~ go 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  [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 " for more information about a command.

Mod历程

时间线:

Go 1.12

event: Go 1.12发布 Modules 默认为 auto;

February
2019
Go 1.11

event: Go 1.11发布 Modules 作为官方试验;

August
2018
Go 1.7
5 months

event: Go 1.7: vendor 目录永远启用2017年1月 Go 团队发布 Dep,作为准官方试验;

August
2016
Go 1.6
5 months

event: Go 1.6 vendor 机制 默认开启2016年5月 Go 团队的 Peter Bourgon 建立委员会,讨论依赖管理工具,即dep;

February
2016
Go 1.5

event: Go 1.5 实验性质加入 vendor 机制2015年 有人提出了采用语义化版本的草案;

August
2015
Go 1.5以前

event: Go 1.5之前的各种草案;

  • 2015年 govendor,kardianos/govendor;
  • 2015年 gb;
  • 2014年 有人提出 external packages 的概念,在项目的目录下增加一个 vendor 目录来存放外部的包;
  • 2014年 glide
  • 2014年 gopkg.in;
  • 2013年10月 Godep
  • 2012年 goven,github/kr/goven;
  • 2012年 Go发布,只有GOPATH
August
2015

Mod规则

module是发布、版本控制和分发的集合,可以直接从版本控制存储库或模块代理服务器下载包。 go module 主要使用语义化版本、导入兼容性规则、最小版本选择。

语义化版本

版本格式:主版本号.次版本号.修订号,版本号 递增规则如下: 主版本号:当你做了不兼容的 API 修改, 次版本号:当你做了向下兼容的功能性新增, 修订号:当你做了向下兼容的问题修正。 先行版本号及版本编译信息可以加到“主版本号.次版本号.修订号”的后面,作为延伸。

导入兼容性规则

如果新包和旧包具有相同的导入路径,则新包必须向后兼容旧包。

go version

最小版本选择(MVS)

介绍

最小版本选择的关键是偏好选择模块允许的最小版本。

例如

go version

递归构建列表。

go version

最终根据最小版本选择找到每个module的最大版本,那就是满足需求的最小版本。

go version

Go Module 使用Russ Cox提出的最小版本选择算法选择构建包。

主要包括四个操作:

  • 构建当前的构建列表。
  • 将所有模块升级到最新版本。
  • 将一个模块升级到特定的较新版本。
  • 将一个模块降级到特定的旧版本。

构建

go mod

替换

replace C v1.4 => R

go mod

排除

exclude C v1.3

go mod

升级

升级B v1.2到B v1.3

go mod

要保留升级,Go命令将更新Go.mod中的require,它将将B的要求更改为1.3版。它还将在// indirect 注释中添加C 1.4和D 1.3的要求,否则这些版本不会被选择。

降级

C v1.4降级

go mod

Mod文件

格式

x
+
~(~zsh):
  • ➜  ~ cat go.mod
  • #module 指令指定路径,go.mod 必须包含一个module指令
  • module example.com/my/thing 
  • #go 指令后面跟版本号,必须是有效的版本号;go1.17之后,如果没有设置,则默认go1.16
  • go 1.17 
  • #require 指令声明依赖库的最低版本,加载require指令后,go按照MSV生成构建列表。
  • require example.com/other/thing v1.0.2
  • require example.com/new/thing/v2 v2.3.4
  • #exclude 指令可以防止对应版本的加载。
  • exclude example.com/old/thing v1.2.3
  • #replace 指令替换代码库某一版本、或者所有版本,新模块可以为另一模块路径版本或者对应系统的文件目录。
  • replace example.com/bad/thing v1.4.5 => example.com/good/thing v1.4.5
  • #retract 指令撤回版本,例如某个第三方库的某一版本有误,可以添加到此处。
  • retract [v1.9.0, v1.9.5]

命令

go mod 命令
模块感知命令

GO111MODULE

  • on或者未设置: 启用module模式,即使go.mod不存在
  • off: 禁用module模式,使用GOPATH模式
  • auto: go.mod存在或者任意的父目录存在,启用module模式

使用go env命令查看,可以使用go env -w GO111MODULE=on修改。

常用命令
go get
用法:
go get [-d] [-t] [-u] [build flags] [packages]
例子:
#升级特定模块。
$ go get -d golang.org/net
#升级模块,提供主模块中的包导入的包。
$ go get -d -u / ...
#升级或降级到模块的特定版本。
$ go get -d golang.org/x/text@v0.3.2
#更新到模块的主分支机构上的提交。
$ go get -d golang.org/x/text@master
#删除对需要它的模块和降级模块的依赖项
#到不需要它的版本。
$ go get -d golang.org/x/text@none
go list
go list -m
用法:
go list -m [-u] [-retracted] [-versions] [list flags] [modules]
例子:
$ go list -m all
$ go list -m -versions example.com/m
$ go list -m -json example.com/m@latest
go mod graph

打印package引用关系

例如:

x
+
~(~zsh):
  • ➜  crypto-data-etl git:(master) ✗ go list -m all 
  • crypto-data-etl
  • bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898
  • 看到bazil包,想要看是谁使用了,就可以使用该命令
  • ➜  crypto-data-etl git:(master) ✗ go mod graph | grep bazil
  • github.com/containerd/continuity@v0.0.0-20191214063359-1097c8bae83b bazil.org/fuse@v0.0.0-20160811212531-371fbbdaa898
goproxy

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

这个命令可以说是需要经常使用

Mod实践

回顾
初始化 
go mod init [folder]
下载
go get package_link@version
更新
go mod tidy
指定版本
go mod edit -replace=package_link@old_version=package_link@new_version
更新到vendor
go mod vendor
实践
前辈蜜汁操作

比如前辈自己拷贝的库,tag对应代码不对,需要针对某个commit id拉取代码;

go mod edit -require github.com/windless0530/redis-go-cluster@f6b361520b1277d838c4e44efe8628caddc9900b

如图:

自己 fork repo
过时不过气包

比较老旧的包,定位当前使用版本,要注意找到包的tag名称。由于不能升级,所以需要定位到特定tag。

go mod edit -replace github.com/apache/thrift=git.apache.org/thrift.git@0.9.3.1

如图:

历史遗留
开发者不坑人

开发者改了githubusername,比如这位logrus开发者

go mod edit -replace github.com/Sirupsen/logrus=github.com/sirupsen/logrus@v1.6.0

如图:

改名咯
本地的公共包

go mod edit -replace=go-base=../go-base

此处有个问题,就是在自己本地的相对路径,其他同事并不可通用,此时需要另一个命令,go.work go的工作区模式,将replace本地目录,移到本地的工作区中。

详细资料

JS
Arrow Up