go module go.mod

2023-05-16

这一次,彻底掌握go mod

1. 版本号规范

go mod 对版本号的定义是有一定要求的,它要求的格式为 v<major>.<minor>.<patch>,如果 major 版本号大于 1 时,其版本号还需要体现在 Module 名字中。比如 我的项目 github.com/pibigstar/go-demo,如果我的版本号增长到 v2.x.x 时,我的 Module 名字也需要相应的改变为: github.com/pibigstar/go-demo/v2, 有人可能就要问了,我不改可以吗? 可以的!但是 go mod 会在你依赖的后面打一个 +incompatible 标志

2. 伪版本

我们将项目上传到 github 后,如果不打 tag,或 tag 不符合 v<major>.<minor>.<patch> 这个格式,那么当我们用 go mod 去拉这个项目的时候,就会将 commitId 作为版本号,它的格式大概是 vx.y.z-yyyymmddhhmmss-abcdef格式

虽然不太好看,但是这个玩意其实挺有用的,省的你每次都需要打 tag 了,这里介绍一个直接拉取小技巧

require (

github.com/pibigstar/go-demo master

)

我们直接在后面写 master 分支,这样它就会拉取 master 分支最后一次提交的 commitId 作为版本号

3. indirect 标志

我们用 go mod 的时候应该经常会看到 有的依赖后面会打了一个 // indirect 的标识位,这个标识位是表示 间接的依赖。

什么叫间接依赖呢?打个比方,项目 A 依赖了项目 B,项目 B 又依赖了项目 C,那么对项目 A 而言,项目 C 就是间接依赖,这里要注意,并不是所有的间接依赖都会出现在 go.mod 文件中。间接依赖出现在 go.mod 文件的情况,可能符合下面的场景的一种或多种:

  • 直接依赖未启用 Go module
  • 直接依赖 go.mod 文件中缺失部分依赖

3.1 直接依赖未启用 Go module

如下图所示,Module A 依赖 B,但是 B 还未切换成 Module,即没有 go.mod 文件,此时,当使用 go mod tidy 命令更新 A 的 go.mod 文件时,B 的两个依赖 B1 和 B2 将会被添加到 A 的 go.mod 文件中(前提是 A 之前没有依赖 B1 和 B2),并且 B1 和 B2 还会被添加 // indirect 的注释。

那么项目 A 的依赖关系就会变成下面这个样子

require (

B vx.x.x

B1 vx.x.x // indirect

B2 vx.x.x // indirect

)

3.2 go.mod 文件中缺失部分依赖

如下图所示,Module B 虽然提供了 go.mod 文件中,但 go.mod 文件中只添加了依赖 B1,那么此时 A 在引用 B 时,则会在 A 的 go.mod 文件中添加 B2 作为间接依赖,B1 则不会出现在 A 的 go.mod 文件中。

此时项目 A 的依赖关系就会变成下面这个样子

require (

B vx.x.x

B2 vx.x.x // indirect

)

间接依赖出现在 go.mod 中,可以一定程度上说明依赖有瑕疵,要么是其不支持 Go module,要么是其 go.mod 文件不完整。

由于 Go 语言从 v1.11 版本才推出 module 的特性,众多开源软件迁移到 go module 还需要一段时间,在过渡期必然会出现间接依赖,但随着时间的推进,在 go.mod 中出现 //indirect 的机率会越来越低。

出现间接依赖可能意味着你在使用过时的软件,如果有精力的话还是推荐尽快消除间接依赖。可以通过使用依赖的新版本或者替换依赖的方式消除间接依赖。

3.3 如果查找间接依赖

可以通过 go mod why -m <pkg> 来查看这个间接依赖是被谁引入的

4. replace 使用

replace 指替换,它指示编译工具替换 require 指定中出现的包

这里要注意两点:

  • replace 只在 main module 里面有效(#add,即当前项目的go.mod中有效)

什么叫 main module? 打个比方,项目 A 的 module 用 replace 替换了本地文件,那么当项目 B 引用项目 A 后,项目 A 的 replace 会失效,此时对 replace 而言,项目 A 就是 main module

  • replace 指定中需要替换的包及其版本号必须出现在 require 列表中才有效

这里我再简单谈下 replace 的使用场景

  • 替换无法下载的包
  • 替换本地自己的包
  • 替换 fork 包

有时候我们依赖的第三方库可能有 bug,我们就可以 fork 一份他们的库,然后自己改下,然后通过 replace 将我们 fork 的替换成原来的

5. exclude 使用

go.mod 文件中的 exclude 指令用于排除某个包的特定版本,其与 replace 类似,也仅在当前 module 为 main module 时有效,其他项目引用当前项目时,exclude 指令会被忽略。

exclude 指令在实际的项目中很少被使用,因为很少会显式地排除某个包的某个版本,除非我们知道某个版本有严重 bug。 比如指令 exclude github.com/pibigstar/go-demo v1.1.0,表示不使用 v1.1.0 版本。

6. 包缓存

最后简单谈一下当我们使用 go mod 后包缓存存储问题,依赖包存储在 $GOPATH/pkg/mod,该目录中可以存储特定依赖包的多个版本。需要注意的是 $GOPATH/pkg/mod 目录下有个 cache 目录,它用来存储依赖包的缓存,简单说,go 命令每次下载新的依赖包都会在该 cache 目录中保存一份,每个版本都会有一份缓存。

值得注意的是包名大小写问题,有时我们使用的包名中会包含大写字母,GOMODULE 模式下,在存储时会将包名做大小写编码处理,即每个大写字母将变 !+相应的小写字母,比如 github.com/pibigstar/GO-demo 包在存储时将会被放置在 $GOPATH/pkg/mod/github.com/pibigstar/!g!o-demo 目录中。所以这里我不推荐你用大写字母定义包名

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

go module go.mod 的相关文章

随机推荐

  • 串口服务器的原理及使用方法

    串口服务器是将来自TCP IP协议的数据包 xff0c 解析为串口数据流 xff1b 反之 xff0c 也可以将串口数据流打成TCP IP协议的数据包 xff0c 从而实现数据的网络传输 它能多个串口设备连接并能将串口数据流进行选择和处理
  • tcpdump命令

    tcpdump tcpdump命令介绍 tcpdump xff0c 用简单的语言概括就是dump the traffic on a network xff0c 是一个运行在linux平台可以根据使用者需求对网络上传输的数据包进行捕获的抓包工
  • 小程序登录后,接口调用失败返回401

    问题描述 xff1a 小程序登录后 xff0c 所有的内部接口不可调用 xff0c 全部授权失败 xff0c 接口返回401 xff1b 解决办法 xff1a 服务端清缓存就可以了 微信开发者工具中 xff0c 小程序多次登录 xff0c
  • 车牌识别算法 基于yolov5的车牌检测+crnn中文车牌识别 支持12种中文车牌识别

    yolov5 车牌识别算法 xff0c 支持12种中文车牌类型 基于yolov5的车牌检测 车牌矫正以及 基于CRNN的车牌识别 1 单行蓝牌 2 单行黄牌 3 新能源车牌 4 白色警用车牌 5 教练车牌 6 武警车牌 7 双层黄牌 8 双
  • LINUX nautilus 命令

    最近使用Ubuntu的时候发现了一个很好用的小命令 xff1a nautilus nautilus是GNOME桌面下的一个文件管理工具 通过这个命令我们可以在终端下非常方便的打开指定目录的文件 nautilus 命令后面一个 xff0c 表
  • 无人机学习之路——电机

    一 什么是电机 xff1f 电机是整个无人机的四肢 xff0c 没有电机来驱动的话整个无人机就无法飞起来 因此我们来重点介绍下电机的一些基础知识 本篇内容不会很详细 xff0c 不会全部介绍 xff0c 只会介绍无人机需要学习的知识 二 电
  • c++中“::”和“:”啥意思

    c 43 43 中 和 啥意思 1 1 类作用域操作符 指明了成员函数所属的类 如 xff1a M f s 就表示f xff08 s xff09 是类M的成员函数 2 表示 域操作符 例 xff1a 声明了一个类A xff0c 类A里声明了
  • python中执行shell脚本之subprocess模块

    一 最近subprocess使用背景和介绍 因为最近领导要求 xff0c 在Python端调用大数据的shell脚本 xff0c 所以需要用到Python来执行shell脚本 因此需要查看下subprocess模块文档 根据官网文档描述 x
  • odroid-xu4(ubuntu mate 16.04)源码编译opencv 3.2

    硬件平台 xff1a odroid xu4 软件环境 xff1a ubuntu mate 16 04 1 更新软件列表 xff1a sudo apt get update 2 安装依赖包 xff1a apt get install libq
  • Pytorch Tensor基本数学运算

    1 加法运算 示例代码 xff1a import torch 这两个Tensor加减乘除会对b自动进行Broadcasting a 61 torch rand 3 4 b 61 torch rand 4 c1 61 a 43 b c2 61
  • HC-SR04超声波测距模块介绍

    超声波简介 超声波是由机械振动产生的 可在不同介质中以不同的速度传播 具有定向性好 能量集中 传输过程中衰减较小 反射能力较强等优点 超声波传感器可广泛应用于非接触式检测方法 它不受光线 被测物颜色等影响 对恶劣的工作环境具有一定的适应能力
  • 操作系统之大端小端

    1 什么是大端 什么是小端 所谓的大端模式 xff0c 是指数据的低位保存在内存的高地址中 xff0c 而数据的高位 xff0c 保存在内存的低地址中 xff1b 所谓的小端模式 xff0c 是指数据的低位保存在内存的低地址中 xff0c
  • 激光雷达授时

    文章目录 前言部分原理图调试微信公众号 前言 给Velodyne的16和32线激光雷达授时 用的是 中科微电子 的 ATGM336H 5N31 部分原理图 部分原理图如下 J9是FAKRA接口 直接挂一个GPS有源天线 出来的TX接一个RS
  • TX2/Xavier Linux GPIO 计算

    目录 Linux GPIO子系统TX2 Linux GPIO计算Xavier Linux GPIO计算参考用C快捷计算TX2 Linux GPIO用C快捷计算Xavier Linux GPIODebug微信公众号 Linux GPIO子系统
  • Android CAN 简记

    文章目录 概要adb 连接adb 常用操作CAN配置脚本SocketCANJNIJNI与SocketCANMakefilejnican java生成的 jnican hjnican c运行github jni can NDKAndroid
  • 在C或C++中如何使用PI(π)值

    span class token macro property span class token directive keyword include span span class token string lt math h gt spa
  • 开发一个Nginx模块hello

    开发一个Nginx模块 用C语言写一个ngx http hello module c的文件 C代码 ngx http hello module c Created on Apr 25 2015 Author lizhenbin includ
  • 升级 GCC 支持C++11

    一 错误发生情景 xff1a 使用sh setup sh安装软件时 xff0c 报以下错误 xff1a configure error A compiler with support for C 43 43 11 language feat
  • C++ 访问http接口

    添加头文件 include lt wininet h gt 附加库 xff1a pragma comment lib 34 Wininet lib 34 发送 int GetURLInternal LPCSTR lpszUrl std st
  • go module go.mod

    这一次 xff0c 彻底掌握go mod 1 版本号规范 go mod 对版本号的定义是有一定要求的 xff0c 它要求的格式为 v lt major gt lt minor gt lt patch gt xff0c 如果 major 版本