奇技指南

最近项目需要开始正式的接触golang的项目,开源项目中使用了最新的以来管理go mod,就跟进了解了相关的一些内容,经过几年的尝试和改进, 现在的版本也是作者希望能够持续十年的设计,也期望能够学习到作者们的思想,提升自己对版本依赖的认识。

本文转载自360云计算

背景介绍

历史介绍

1.Makefile, goinstall和go get

最早是通过Makefile的形式进行编译,连接程序。后来的goinstall能够在无额外配置的情况拉取到相应的代码,此时只能使用在标准库中。go get解决了开发者之间的代码共享问题,能够通过git等进行代码共享。

2.Versioning和API Stability

通过import的路经中添加相应的版本信息达到了引用不同版的效果。

3.Vendoring和Reproducible Builds

由于go get没有版本相关的信息,所以不能提供一个可以可稳定重复的编译过程。vendor通过拷贝相应的代码到vendor目录下,依赖项不会变更除非手动修改其中的依赖项。

4.An Official Package Management Experiment

dep是官方的依赖管理实验项目,主要是用来探索最佳的实践,是找到最终的解决的重要的一步。

解决的问题

  1. 官方的定义

moduleis a collection of related Go packages that are versioned together as a single unit.

Modules record precise dependency requirements and create reproducible builds.

Most often, a version control repository contains exactly one moduledefinedin the repository root.

(Multiple modules are supported in a single repository, but typically that would result in more work

on an on-going basis than a single module per repository).

Summarizing the relationship between repositories, modules, and packages:

A repository contains one or more Go modules.

Eachmodule contains one or more Go packages.

Eachpackage consists of one or more Go source files in a single directory.

Modules must be semantically versioned according to semver, usually in the

form v(major).(minor).(patch), such as v0.1.0, v1.2.3, or v1.5.0-rc.1.

The leading v is required. IfusingGit, tag released commits with their versions.

Publicandprivatemodule repositories and proxies are becoming available (see FAQ below).

module是一组相关的package的集合,作为一个整体进行版本控制。module记录精确的依赖需求并创建可重复的构建。

一个repo可以包含一个或者多个module,一个module可以包含一个或者多个package,一个package是一个路经下包含一个或者多个文件。

module必须是经过语义版本semver的。

1. 版本控制

如何引入一个向下不兼容的版本?

import的兼容规则如下

If an old package and a new package have the same import path,

the new package must be backwards compatible with the old package.

如果使用相同的import路经,则新版本必须是兼容就版本的。go是通过不兼容的版本使用不同的import路经来区分的,

例如 import path和import path/v2的方式

2.同一个主版本采用最低版本选择策略进行版本选择?

最小版本选择,即为选择所有的版本中(不同的主版本是不同的package)选择版本最大的一个版本,也是可用的最小版本。

设计目标

鼓励用户打标签,使得更加的可读,并且能够帮助使用者明确哪些是已经发布的,哪些是正在开发中的不依赖具体的版本控制既可以在一个repo中使用一个module,也可以一个repo下使用多个module,并且各自进行版本控制

能够添加自己的代理

删除之前的vendor目录

基本操作

创建Module

  1. 创建一个目录,新建hello.go文档

package hello

func Hello() string{

return"Hello, world."

}

2.添加相应的测试文档

package hello

import"testing"

func TestHello(t *testing.T) {

want := "Hello, world."

if got := Hello(); got != want {

t.Errorf("Hello() = %q, want %q", got, want)

}

}

3.执行测试,确认程序正常运行

注意需要关闭掉相应的module强制设置,确保GO111MODULE不为on,否则会得到 go: cannot find main module; see 'go help modules'

➜ hello go test

go test

PASS

ok _/home/zhangchao11/work/golang/hello 0.003s

➜ hello

初始化为module

go mod init example.com/hello

查看相应的go.mod

module example.com/hello

go 1.13

执行测试

$ go test

go: finding rsc.io/quote v1.5.2

go: downloading rsc.io/quote v1.5.2

go: extracting rsc.io/quote v1.5.2

go: finding rsc.io/sampler v1.3.0

go: finding golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c

go: downloading rsc.io/sampler v1.3.0

go: extracting rsc.io/sampler v1.3.0

go: downloading golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c

go: extracting golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c

PASS

ok example.com/hello 0.023s

$

说明: go命令能够自动从go.mod中导入指定的依赖项。如果在go.mod中没有找到特定的依赖项的情况

则会从对应的package中自动的查找相应的module,并且把结果写入到go.mod中。导入的module的版本默认选择最新的版本(latest),go.mod中默认自动添加的只有直接依赖的module,并不包含间接依赖的module。

查看新的go.mod

module example.com/hello

go 1.13

require rsc.io/quote v1.5.2

执行test

➜ hello go test

go test

PASS

ok example.com/hello 0.006s

➜ hello

通过上述结果可以看出,第二次执行go test的时候,由于go.mod已经是最新状态,并且需要的module已经缓存在本地了,就不再执行上述的获取,展开的过程了。

查看module的所有依赖

➜ hello go list -m all

go list -m all

example.com/hello

golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c

rsc.io/quote v1.5.2

rsc.io/sampler v1.3.0

➜ hello

列出了module的所以依赖项,第一行列出的是当前module(也称为主module),依赖的module则按照module的路径进行排序列在下面的内容.

查看生成的go.sum

➜ hello cat go.sum

cat go.sum

golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw93ERBE4m30iBm00nkL0i8=

golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

rsc.io/quote v1.5.2 h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3Y=

rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=

rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=

rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

➜ hello

go.sum中保存的是模块对应的哈希值,该值可以保证后续下载的版本和第一次下载的版本没有被非预期的修改。

升级依赖

升级golang.org/x/text

➜ hello go get golang.org/x/text

go get golang.org/x/text

重新检查依赖列表

➜ hello go list -m all

go list -m all

example.com/hello

golang.org/x/text v0.3.2

golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e

rsc.io/quote v1.5.2

rsc.io/sampler v1.3.0

➜ hello cat go.mod

cat go.mod

module example.com/hello

go 1.13

require (

golang.org/x/text v0.3.2// indirect

rsc.io/quote v1.5.2

)

➜ hello

从上面的结果中可以看出,golang.org/x/text从之前的版本已经升级到了v0.3.2的版本,更新之后的版本信息已经添加到了go.mod,后面添加了indirect表明该依赖项不是主module直接依赖的。

查询可用的所有依赖

➜ hello go list -m -versions rsc.io/sampler

go list -m -versions rsc.io/sampler

rsc.io/sampler v1.0.0 v1.2.0 v1.2.1 v1.3.0 v1.3.1 v1.99.99

➜ hello

更新到指定版本

➜ hello go get rsc.io/sampler@v1.3.1

go get rsc.io/sampler@v1.3.1

go: finding rsc.io/sampler v1.3.1

go: downloading rsc.io/sampler v1.3.1

go: extracting rsc.io/sampler v1.3.1

➜ hello

添加一个新的主版本

添加quoteV3版本

package hello

import(

"rsc.io/quote"

quoteV3 "rsc.io/quote/v3"

)

func Hello() string{

return quote.Hello()

}

func Proverb() string{

return quoteV3.Concurrency()

}

添加对应的测试代码

func TestProverb(t *testing.T) {

want := "Concurrency is not parallelism."

if got := Proverb(); got != want {

t.Errorf("Proverb() = %q, want %q", got, want)

}

}

执行测试

➜ hello go test

go test

go: finding rsc.io/quote/v3 v3.1.0

go: downloading rsc.io/quote/v3 v3.1.0

go: extracting rsc.io/quote/v3 v3.1.0

PASS

ok example.com/hello 0.006s

➜ hello

获取最新的依赖关系

➜ hello go list -m all

go list -m all

example.com/hello

golang.org/x/text v0.3.2

golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e

rsc.io/quote v1.5.2

rsc.io/quote/v3 v3.1.0

rsc.io/sampler v1.3.1

➜ hello

不同的主版本采用不同的导入路径,通过这种方式来提供不兼容的版本升级。v0,v1是直接使用module的路径就可以了,v2及以上的版本必须要添加相应的版本信息path/v2等方式。同一个主版本的不同子版本必须要保证向下的兼容性,也就是同一个主版本只会选择一个版本。这种方式保证了我们在使用新版本的特性的时候,又可以暂时不迁移依赖旧版本的代码。

删除不再使用的依赖

查看现有的依赖关系

➜ hello go list -m all

go list -m all

example.com/hello

golang.org/x/text v0.3.2

golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e

rsc.io/quote v1.5.2

rsc.io/quote/v3 v3.1.0

rsc.io/sampler v1.3.1

➜ hello cat go.mod

cat go.mod

module example.com/hello

go 1.13

require (

golang.org/x/text v0.3.2// indirect

rsc.io/quote v1.5.2

rsc.io/quote/v3 v3.1.0

rsc.io/sampler v1.3.1// indirect

)

➜ hello

从上面的依赖列表中还是依然又v1.5.2,go build或者go test这样的命令,能够添加没有的以来项目但是不能够安全的删除掉相应的依赖。安全的删除一个依赖需要检查module里面的所有package是否依赖该module,而build,test命令都没有加载相应的信息,所以不能够安全的删除相应的module。

go mod tidy

➜ hello go mod tidy

go mod tidy

➜ hello go list -m all

go list -m all

example.com/hello

golang.org/x/text v0.3.2

golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e

rsc.io/quote/v3 v3.1.0

rsc.io/sampler v1.3.1

➜ hello cat go.mod

cat go.mod

module example.com/hello

go 1.13

require (

golang.org/x/text v0.3.2// indirect

rsc.io/quote/v3 v3.1.0

rsc.io/sampler v1.3.1// indirect

)

➜ hello

通过这个命令能够删除掉不再需要的依赖module

问题

1.go list -m all?

按照什么排序策略进行排序

2.提交代码的时候一定要提交go.mod和go.sum不然会出现checksum的时候出错的情况

使用中遇到的问题

如何进行依赖库的代码开发?

可以用replace的方式,replace可以替换成本地的路经,来达到使用本地代码的作用。

replace github.com/brocaar/lorawan v0.0.0-20190814113539-8eb2a8d6da09=> path/lorawan

如何使用自由仓库进行依赖库的开发?

设置git的地址转化就可以达到预期的目的,是否可以通过proxy的形式来做到类似的效果,还没有具体研究,后面会去研究以下proxy相关的内容。

git config --global url."${UrlPath}lorawan.git".insteadOf "https://github.com/brocaar/lorawan"

go.mod和go.sum的提交?

提交相应的变更的时候,务必记得提交相应的go.sum,不然会出现后续的sum检查不通过。

关注我们

界世的你当不

只做你的肩膀

360官方技术公众号

技术干货|一手资讯|精彩活动

空·

没有规则可制作目标modules_Modules简介相关推荐

  1. make[2]: *** 没有规则可制作目标“/home/.../src/viewer.cpp”,需求。 停止... recipe for target ‘.....‘failed问题解决

    在学习PCLVisualizer可视化时,遇到了以下问题,浪费了我好多时间,希望可以帮到大家: 1.问题描述 1.1. 很多未定义 1. 2.没有规则可制作目标问题 2.问题解决 分析:就是CMake ...

  2. make: *** 没有规则可制作目标“distclean”。 停止。_Makefile伪目标

    这一个章节我们主要讲的是 Makefile 中的伪目标.所谓的伪目标可以这样来理解,它并不会创建目标文件,只是想去执行这个目标下面的命令.伪目标的存在可以帮助我们找到命令并执行.使用伪目标有两点原因: ...

  3. 解决在ros catkin_make编译时出现“make[2]:*** 没有规则可制作目标“的问题

    问题如图: 解决方法: 法一:将不build和devel文件夹都删掉,再次catkin_make即可 有时候该方法也解决不掉,可以试试下面的方法. 法二: 把导致编译失败的功能包先移出工作空间,删掉b ...

  4. make: *** 没有规则可制作目标“check_python_dependencies”......问题解决方法

    一.解决办法 1.通过运行以下命令来安重新装 python -m pip install --user -r $IDF_PATH/requirements.txt 2.解释器的版本号可以通过运行命令以 ...

  5. make[1]: *** 没有规则可制作目标“/build”

    KERN_VER = $(shell uname -r) KERN_DIR = /lib/modules/$(KERN_VER)/build 解决办法: 1.新建一个build文件夹 2.检查KERN ...

  6. make[2]:***没有规则制作目标XXX,由XXX需求。停止。

    记录一次驱动编写中遇到的错误. 写了一个简单的驱动,编写Makefile,内容如下: #模块名称 obj-m:=xxx.o #kernel路径 KDIR:=/yyy/zzz #获取当前路径 PWD?= ...

  7. 3D/VR游戏制作软件GameStudio简介

    3D/VR游戏制作软件GameStudio简介 2004-4-30 作者:虚怀若谷 转载自:5D多媒 网友评论 2 条 点击进入论坛 前言:GameStudio是一个可以制作3D/VR游戏的软件,通过 ...

  8. 怎么制作百度百科简介,创建自己的百度百科怎么弄

    很多人想要为自己创建一个百度百科词条但是却不知道怎么弄,下面洛希爱做百科网为大家介绍怎么制作百度百科简介. 创建百科的流程和规定: 首先是注册百度百科账号 仅有申请注册了百度帐号,才可以在百科里边开展 ...

  9. 自己制作目标检测数据集

    自己制作目标检测数据集 这里介绍2个制作目标检测数据集的工具:labelImg和labelme.用pip list查看自己电脑是否已安装这两个库,没有的话分别用pip install labelImg ...

最新文章

  1. 跳过51单片机,直接学STM32有什么严重后果?
  2. cmd编译java文件中文乱码_乱码 HelloWorld 世界你好 cmd 执行输出的中文java 显示乱码 解决 另附 win无法执行编译运行javac java编译文件的解决方案...
  3. AtCoder SoundHound Inc. Programming Contest 2018 E + Graph (soundhound2018_summer_qual_e)
  4. linux 自动安装系统,cobbler 自动安装linux系统
  5. Spring Boot Starter 常用列表
  6. jfinal分页时使用like
  7. js打印(控件)及多种方式
  8. 面向流批一体的 Flink Runtime 新进展
  9. 一个快播倒下去,千千万万个快播站起来
  10. matlab实现像素分类,定义使用 Tversky 损失的自定义像素分类层
  11. 智慧交通:数智化地铁大屏管控运维平台
  12. 使用 CSS 创建自定义鼠标光标
  13. 排列组合之生成排列_(:з」∠)_
  14. 【ACL Findings 2021】Does Robustness Improve Fairness? Approaching Fairness with Word Substitution R
  15. 小a与星际探索 线性基算法
  16. Spring 4 - AOP
  17. 华为手机(Android系统)备忘录转移至iOS
  18. fzu-1753 Another Easy Problem-快速求N!中有多少个p
  19. Win10删除文件权限不足的一种可能的解决方式
  20. 【Matlab人脸识别】KL变换人脸识别【含GUI源码 859期】

热门文章

  1. 三月数据库技术通讯.pdf | Oracle配置DCD避免会话被防火墙强制断开
  2. DBASK问答集萃第二期
  3. 华为云发布【云巢】智慧康养物联网加速器,加入立享多项扶持
  4. 【华为云技术分享】云图说 | ContainerOps推出灰度发布模式,助力企业落地容器DevOps最佳实践
  5. Python批量检测服务器端口可用性与Socket函数使用
  6. 【nodejs原理源码赏析(4)】深度剖析cluster模块源码与node.js多进程(上)
  7. 带着canvas去流浪系列之二 绘制折线图
  8. memcache入门
  9. Tensorflow2.x代码实现计算Top-k Accuracy
  10. 回望2019,展望2020