Go基础-依赖管理

蚀窗多态
• 阅读 279

在Go语言编程中,我们经常会接触到依赖管理。简单来讲,这是对项目所需外部包的管理,包括确定所需外部包及其正确版本,并确保在构建和测试项目时其存在。

基础依赖管理则涉及到添加、更新和删除依赖包,锁定依赖包版本等工作。尽管看似琐碎,但这些工作对项目开发至关重要。

但实际上,go的依赖管理让人一言难尽,甚至可以说乱成一团。官方推出了好几种管理机制,比如gopath、vender、dep等,但都用起来不是那么顺手。到了Go 1.11版本,推出了go mod,虽然稍微好些,但和maven比起来,还是差了好几条街。

更让人费解的是,Go居然没有像maven、pip那样的官方依赖包站点。第三方包可以在任意开源站点发布,这就导致了一堆问题,比如下载地址、版本管理、包说明文档等。

由于没有统一的下载地址,Go的解决方案是把包名就当做包的下载地址。虽然很多包都发布在github.com,但也有很多包用其他站点发布,比如k8s.io、bazil.org、gobot.io等等。这就导致无法建立加速镜像站点,国内的加速都只能通过代理的方式。

包名的格式也有限制,只要是会被其他项目用到的包,名字就得是下载地址。就算是公司内部的私有包也不能例外,否则就得人工维护依赖。

包的文档格式和API说明也没有标准,直到go官方推出了pkg.go.dev站点,才统一了文档风格和包检索。但奇怪的是,这个站点只提供包信息和展示,包还是得在各自的站点发布。

吐槽归吐槽,要用的时候我们还是得用go语言,下面我会给大家讲一讲go的那些管理机制。

Gopath

GOPATH是Go的一个重要环境变量,被称为工作目录。在Go 1.5版本之前,通过执行go get ${packageName}命令,我们可以下载依赖包。这个命令总是下载最新版本的依赖包,并且这些依赖包都会被存放在${GOPATH}/src目录下,但是并没有版本控制。

当我们使用import命令导入依赖包时,会按照以下路径查找:${GOROOT}/src -> ${GOPATH}/src。其中,${GOROOT}/src是Go SDK的安装目录,src文件夹存放了Go的标准库。而${GOPATH}/src则是Go的工作目录,src文件夹存放了所有的Go项目。

需要注意的是,当我们需要导入项目内部模块时,也需要从这些固定路径计算,因此所有项目都必须放在工作目录下,否则会出现找不到依赖的问题。这与其他语言有很大的区别,例如Java和Python都支持从项目路径计算,这意味着项目可以放在任意目录。

例如,如果我们的项目名称是demo,那么导入依赖的方式如下:

import "fmt"                               // 导入标准库包
import "demo/utils"                        // 导入项目内的工具模块包, 注意也从绝对路径查找
import "github.com/forgoer/openssl"        // 导入外部第三方包

fmt是Go语言的标准库,它的源代码位于GOROOT/src目录下。其他非标准库的包,例如你自己编写的包或者第三方包,都应该放在GOPATH/src目录下。这是Go语言的包管理机制决定的,它帮助Go语言在编译时找到所需要的包。

如果你想修改fmt包的代码,你可以直接在GOROOT/src目录下找到fmt包的源代码进行修改。

但是,我不推荐你这样做,因为这样会改变Go语言的标准行为。

如果你只是想使用修改过的fmt包,你可以在GOPATH/src目录下创建一个新的包,然后在新包中导入fmt包,并在新包中添加或修改你需要的功能。这样,你的代码就可以使用修改过的fmt包,而不会影响到其他使用标准fmt包的代码。

Vender

Go 1.5版本引入了一个新的特性,叫做vendor机制。这个机制允许每个项目在其目录下有一个名为vendor的文件夹,用来存放该项目所依赖的包。在执行go build命令时,Go语言会首先在vendor目录下查找依赖,如果没有找到,才会去GOPATH目录下查找。依赖查找的顺序是:${GOROOT}/src -> ${Project}/vendor -> ${GOPATH}/src

vendor机制的出现主要是为了解决依赖版本管理的问题。

它的基本思想是,每个项目的依赖都可以在自己的目录下独立管理,这样就避免了不同项目之间的依赖冲突。但是,这个机制并没有解决依赖包的版本问题,只是将依赖包放在了独立的目录下。如果你想要固定依赖包的版本,你需要将整个vendor目录一起提交到代码仓库。

这种做法虽然在一定程度上解决了版本管理的问题,但是也带来了一系列新的问题。

首先,vendor目录通常会非常大,提交到代码仓库会占用大量的空间,并且会降低仓库的下载和更新速度。

其次,大量的依赖代码会干扰代码审查,对代码统计和其他性能工具也会产生影响。

最后,对于多人协作的项目来说,管理项目的依赖包,记录版本,获取和存放依赖包等工作会变得更加复杂。从某种意义上说,蛮鸡肋的。

Go mod

它是从Go1.11版本开始引入的模块支持(module)功能的一部分,比起其他依赖管理,挺实用的。GoMod提供了对依赖包的自动获取、版本控制、依赖图分析等功能。
每个项目都会新增一个go.mod文件,用于维护该项目的依赖包信息,包括依赖包的版本号。可以使用go mod init ${ProjectName}命令来创建这个文件,而文件的内容则由Go自动维护。每次下载或升级依赖时,Go都会自动更新这个文件。

要使用go mod,需要先通过环境变量GO111MODULE来启用这个功能。"off"意味着关闭go mod,Go将继续从vendor目录或GOPATH中查找依赖。"on"则表示开启go mod,这时项目必须包含go.mod文件。如果没有设置环境变量,或者设置为"auto"(这是Go 1.13及以后版本的默认模式),那么Go会自动判断是否启用go mod:如果项目不在GOPATH/src目录下,并且包含go.mod文件,那么Go就会启用go mod。

使用GoMod的好处包括:

  1. 简化依赖管理:你不再需要将所有的依赖复制到你的项目目录下,GoMod会自动为你下载和管理这些依赖。
  2. 便于协作:当其他开发者克隆你的项目时,他们不需要手动安装所有的依赖,只需要运行go mod download命令即可。
  3. 便于版本控制:你可以在go.mod文件中明确指定依赖的版本,这样就可以避免因为依赖包的更新导致的不兼容问题。
  4. 提供依赖图分析:通过go mod graph命令,你可以查看项目的依赖图,了解各个依赖之间的关系。

当然go mod也有其他的操作:
go mod download :手动触发下载依赖包到本地 cache
go mod graph :打印项目的模块依赖结构
go mod edit :编辑 go.mod 文件
go mod verify:校验模块是否被篡改过
go mod why: 查看为什么需要依赖
go mod vendor:导出项目所有依赖到 vendor 下

总的来说,GoMod是一个强大且易用的依赖管理工具,它可以极大地提高Go语言开发的效率和质量。

点赞
收藏
评论区
推荐文章
徐小夕 徐小夕
3年前
lerna + dumi + eslint多包管理实践
背景在开发大型项目时,我们通常会遇到同一工程依赖不同组件包,同时不同的组件包之间还会相互依赖的问题,那么如何管理组织这些依赖包就是一个迫在眉睫的问题.我们目前已有的方案有:Multirepo(多个依赖包独立进行git管理)和Monorepo(所有依赖库完全放入一个项目工程).Multirepo的缺点在于每个库变更之后,需要发布到线上,然后在项目
Node工程的依赖包管理方式
在前端工程化中,JavaScript依赖包管理是非常重要的一环。依赖包通常是项目所依赖的第三方库、工具和框架等资源,它们能够帮助我们减少重复开发、提高效率并且确保项目可以正确的运行。
kenx kenx
3年前
Maven 基础标签之版本管理和冲突解决
前言我们在做java项目的时候由于jar包太多,我们就需要使用maven做项目管理,管理项目的jar包依赖,包括打包上线maven基础Maven是一个项目管理工具,主要用于项目构建,依赖管理,项目信息管理每个maven项目根目录都会有一个pom.xml文件,负责项目构建,依赖管理在这个文件里面,你只需要添加相应的jar包坐标配置,maven就会自动
Stella981 Stella981
3年前
Maven项目使用打包时使用本地jar包库
在使用maven管理项目时,有时候我们可能会使用一些第三方的jar包依赖库,但是这些jar包依赖库又没有在共有的maven仓库。通常只能下来放到本项目的lib目录下。但是我们打包时如果不做处理,那么打包后的fatjar中不会有lib文件夹中的相关jar包。打包后无法运行起来,因此需要做特殊处理,让maven打包时能够把使用到外部jar打进去。主要就是在
Wesley13 Wesley13
3年前
go mod 无法自动下载依赖包的问题
go11以后启用了gomod功能,用于管理依赖包。当执行gomodinit生成go.mod文件之后,golang在运行、编译项目的时候,都会检查依赖并下载依赖包。在启动了gomod之后,通过gomod下载的依赖包,不在放在GOPATH/src中,而是放到GOPATH/pkg/mod中。比如我当前的GO
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
gh
ghost实战运用一、安装步骤1、环境go版本:1.10.3ghost版本:1.0.462、安装go语言安装go依赖包yuminstallbisonedgawkgcclibc6devmakey
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Maven进阶学习指南 | 京东云技术团队
当我们在开发项目时,有时需要用到外部依赖组件,例如当我们需要Json序列化的时候需要用到FastJson组件,我们可以通过下载对应jar包加载到项目中。但当一个大的项目同时需要依赖各种各样的外部服务,就存在着配置繁琐、依赖冲突等问题,因此可以通过maven来完成对应的依赖管理功能。
死牛胖子 死牛胖子
11个月前
Maven如何解决版本依赖冲突
Maven的依赖具备传递性,一个项目会依赖很多包,这些依赖包又会依赖其它包,从而构成复杂的依赖关系,这其中相同的包可能会被多次依赖,如果依赖了多个版本,就会产生冲突,此时,Maven需要一个选择策略,从多个版本中选择一个版本。Maven会根据以下两个原则来
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
蚀窗多态
蚀窗多态
Lv1
且向路人举杯尽,共醉一场又何妨
文章
4
粉丝
0
获赞
0