Tony Bai · Go 语言第一课
Tony Bai
资深架构师,tonybai.com 博主
21492 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 59 讲
开篇词 (1讲)
结束语 (1讲)
Tony Bai · Go 语言第一课
15
15
1.0x
00:00/00:00
登录|注册

06|构建模式:Go是怎么解决包依赖管理问题的?

选择符合项目整体要求的“最小版本”
导入路径中引入主版本号区别不兼容版本
主版本号、次版本号、补丁版本号
版本号格式:vX.Y.Z
go build
go mod tidy
go mod init
选择符合项目整体要求的“最小版本”
导入路径中引入主版本号
版本号规范
最小版本选择
语义导入版本
创建第一个Go Module
问题:影响代码仓库空间、代码评审、依赖包管理
在项目的vendor目录下缓存项目的所有依赖
问题:版本控制、可重现构建、依赖包管理
go get命令下载缺失的第三方依赖包
Go编译器在GOPATH配置的路径下搜索第三方依赖包
迁移基于GOPATH构建模式的项目为Go Module构建模式
Go 1.16版本
Go 1.13版本
Go 1.13版本之前
GO111MODULE环境变量
最小版本选择原则
语义导入版本机制
Go Module
Vendor机制
GOPATH构建模式
思考题
Go各版本构建模式机制和切换
深入Go Module构建模式
构建模式演化的前世今生
Go构建模式演化

该思维导图由 AI 生成,仅供参考

你好,我是 Tony Bai。
通过前面的讲解,我们已经初步了解了 Go 程序的结构,以及 Go 项目的典型布局了。那么,接下来,我们是时候来系统学习一下 Go 应用的构建了,它们都是我们继续 Go 语言学习的前提。
所以在这一节课,我们就来了解 Go 构建模式演化的前世今生。理解了这个发展史后,我们会重点来探讨现在被广泛采用的构建模式,Go Module 的基本概念和应用构建方式。  接着,知道了怎么做后,我们会再深一层,继续分析 Go Module 的工作原理。这样层层深入地分析完后,你就能彻底、透彻地掌握 Go Module 构建模式了。
好了,我们直接开始吧。我们先来了解一下 Go 构建模式的演化过程,弄清楚 Go 核心开发团队为什么要引入 Go module 构建模式。

Go 构建模式是怎么演化的?

Go 程序由 Go 包组合而成的,Go 程序的构建过程就是确定包版本、编译包以及将编译后得到的目标文件链接在一起的过程
Go 语言的构建模式历经了三个迭代和演化过程,分别是最初期的 GOPATH、1.5 版本的 Vendor 机制,以及现在的 Go Module。这里我们就先来介绍一下前面这两个。
首先我们来看 GOPATH。
Go 语言在首次开源时,就内置了一种名为 GOPATH 的构建模式。在这种构建模式下,Go 编译器可以在本地 GOPATH 环境变量配置的路径下,搜寻 Go 程序依赖的第三方包。如果存在,就使用这个本地包进行编译;如果不存在,就会报编译错误。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Go Module构建模式是Go语言包依赖管理的重要发展趋势。文章深入探讨了Go Module的语义导入版本机制和最小版本选择原则,强调了Go Module构建模式的创新性和重要性。通过语义版本规范,Go命令可以确定版本发布的先后次序和兼容性,同时Go Module的最小版本选择原则为项目选择符合整体要求的“最小版本”,提供了持久和可重现的构建方案。此外,文章还介绍了Go各版本构建模式机制和切换,帮助读者更好地理解不同版本下、不同构建模式下的行为特性。文章还提到了Go 1.11版本中,Go核心团队推出了新一代构建模式:Go Module以及一系列创新机制,包括语义导入版本机制、最小版本选择机制等。Go Module构建模式将成为Go语言唯一的标准构建模式。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Tony Bai · Go 语言第一课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(69)

  • 最新
  • 精选
  • 张诚
    目前网上讲包管理讲得最清晰最全面的内容了。

    作者回复: 过奖了:)

    2021-10-25
    7
    75
  • 若水清菡
    之前看过两个老师讲go,上来基本上都适合先语法规则后实践的路线,每次go build都一脸懵逼,看下来还是不了解go的编译过程~~~~tony bai老师讲的非常好,遇到一位合适自己的老师,希望跟着学完这门课程,非常感谢老师~

    作者回复: 嗯嗯,这次的思路是先让大家上手。但作为入门课,后续必然也会对Go语法进行讲解与深入理解的。

    2021-11-14
    2
    18
  • lesserror
    感谢 Tony Bai 老师的分享,每篇文章我都认真拜读了。 本着持续精进的目的,每篇文章我都会提出一些自己的疑问,麻烦老师抽空解答一下。 1. 在$GOPATH模式下,寻找第三方包依赖的顺序是不是:先找 $GOROOT 然后找 $GOPATH。 2. go.sum文件的工作原理后面能否详细讲讲吗? 感觉这里的讲解还是简单带过了。 3. 文中说:“Go 团队认为“最小版本选择”为 Go 程序实现持久的和可重现的构建提供了最佳的方案。” 这句话能展开讲讲吗? 感觉没明白其中的意思。 4. 第4讲说到:“Go 支持在一个项目 / 仓库中存在多个 module,但这种管理方式可能要比一定比例的代码重复引入更多的复杂性。” 如果项目中引入了第三方 module,比如这篇文章中也引入了第三方 module,这种情况属于 : "在一个项目 / 仓库中存在多个 module" 的情况吗?

    作者回复: 你的提问就是对专栏最好的支持,手工点赞! 下面回答你的问题: 1. 从gopath模式下,go build命令的输出来看,是这样的。 2. go.sum机制对于大多数开发人员都是透明的,属于高级话题。因此,在我的这个以入门和基础为重的专栏中并未深入展开。后>续我可能会在自己的博客或公号上谈谈go.sum机制,到时候,你可以去看看。 3. 相较于选择最新最大版本,选择最小版本出于几个考虑吧: 1)对开发者而言,更易于理解和预测,就像课程中例子那样,我们根据依赖图可以很容易确定程序构建最终使用的依赖版本。 2) 对go核心团队来说,更容易实现,据说实现最小选择的代码也就几十行。 3) 更重要的是最小版本选择更容易实现可重现构建。试想一下,如果选择的是最大最新版本,那么针对同一份代码,其依赖包的最新最大版本在不同时刻可能是不同的,那么在不同时刻的构建,产生的最终文件就是不同的。 当然这一切的前提都是基于语义版本规范,对于不符合规范的module,相当于没有遵守契约,这套规则也就失效。这对任何语言来 说都是一样的。 4. 不属于。04讲说的那种情况是指在一个项目仓库中的不同目录下放置了多个go.mod,即一个项目中有多个module。

    2021-10-25
    3
    18
  • flexiver
    老师,您好。想要请问解答两个问题: 1、请问在构建module时, go mod init -module path, 这个module path 是固定要写成github.com/module name这样一个结构吗?

    作者回复: 好问题!不必要非得是github.com,也不必要非得是github.com/module name这样的。你可以使用module demo1这样的path。不过module path有三个作用,根据需要作出path的选择: 1. 定位代码仓库位置。如果你的代码是开源到一些公共代码托管站点,或者在组织内部的代码仓库时,path中要带上仓库的地址,比如github.com/repo/module,这样依赖你的module的其他代码可以找到你的module代码。 2. 如果你的module不在repo的根路径下,那么在module path中还要包含子目录路径。以github.com/etcd-io/etcd这个仓库为例。这个仓库下管理着多个go module。以其子目录raft下面的module为例,这个module的path为:module go.etcd.io/etcd/raft/v3。其中的raft就是子路径。 3. major版本号。如果major>=2,需要在module path中加上major号后缀。就像上面的module go.etcd.io/etcd/raft/v3。

    2022-03-13
    4
    13
  • 丶能
    提问! “选择符合项目整体要求的最小版本”是可能选择,依赖最小版本与最新版本中任意版本,还是项目引入版本中的可选范围内的最小版本呢?

    作者回复: 按照课程中的例子,A 要求 >=C v1.1.0,B 要求 C >=v1.3.0,那么选择同时满足A与B要求的最小版本,就是v1.3.0。如果选择v1.1.0则不满足A要求。

    2021-10-25
    11
    12
  • 太匆匆
    默认是是最小版本原则,能否修改默认呢?比如举例当中的v1.1.0、v1.3.0、v1.7.0默认会选v1.3.0,开发者能否将其改成v1.7.0呢?

    作者回复: 好问题!可以通过go get xxx@v1.7.0显式更新go.mod中的依赖版本。或通过go mod edit命令或直接编辑go.mod进行。

    2022-03-23
    2
    11
  • 独钓寒江
    老师你好,最近 log4j 和 logback 都被发现了安全漏洞,很多Java程序都受到影响,修复起来工作量也不小。如果类似情况出现在Go方面,例如 logrus 出了安全漏洞,我们需要修改依赖版本, 我们可以怎么应对呢?可以简单说说吗?

    作者回复: 你这个问题很"与时俱进"啊:)。首先对于已经依赖logrus的版本的go项目,go build不会自动更新logrus到其最新版本,也就不会受到故意漏洞的侵害。假设你的项目在go mod init时获取到的是最新漏洞版本或通过go get logrus@latest获取到其漏洞版本,那么可以看一下07讲,将版本降级或升级到漏洞修复后的版本,操作步骤专栏里都有的。

    2021-12-25
    3
    7
  • 李亮
    关于依赖管理的文档在这里:https://go.dev/doc/modules/managing-dependencies

    作者回复: 👍

    2022-11-01归属地:北京
    5
  • ゝ骑着小车去兜风。
    之前做过一个go的项目,用的iris框架,然而拉下来的包始终没有我需要的那个方法,纠结了好久都没办法解决。 现在终于知道是iris框架更新了,导致主板本号不同,需要的那个方法也变成另一个方法了。

    作者回复: 👍

    2022-04-30
    4
    5
  • 每天晒白牙
    老师,请教个问题,我是go1.16.4版本,按照老师在文中所说,GO111MODULE 应该为on呀,而我的确实空 (base) ➜ ~ go env GO111MODULE="" GOARCH="amd64" .... GOVERSION="go1.16.4"

    作者回复: 所谓默认为on是指,如果GO111MODULE没有显式设置,那么默认为on。你这里环境变量GO111MODULE为空,那么go编译器默认GO111module为on。

    2022-05-10
    2
    4
收起评论
显示
设置
留言
69
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部