概述
Go工程和依赖管理基本机制
依赖管理机制的变迁
GoPath—>GoVendor---->GoMod
- GoPath:会要求工程代码要保存在GoPath/src的目录下面。同时要求你的依赖库也要是这个目录下面的:
$GOPATH/src/yourProject/
$GOPATH/src/gorm
:如果依赖了gorm
编译的时候会直接使用GoPath/src目录下的代码。Go Get下载的代码也会放在GoPath中。
往往我们在安装Go以后,通过go env
查看我们的Go Path,进入该文件目录,目录结构是这样的:
├── bin //用来存放编译后的可执行文件
│
├── dlv
│
├── go-outline
│
├── gomodifytags
│
├── gopkgs
│
├── goplay
│
├── gopls
│
├── gotests
│
├── impl
│
└── staticcheck
├── pkg //用于存放编译后生成的归档文件
│
├── mod
│
└── sumdb
└── src // 用来存放go源码文件
└── github.com
这个结构,配上GoPath的要求,我们就必须要把我们的代码写在src文件下。或者是在其他任意目录写代码,但是最后构建的二进制文件要放在src下,才能执行。
刚刚说了,Go Get下载的代码也会放在GoPath中,这样你的工程代码和第三方代码都在同一个目录下,甚至你的多个工程代码也会在一个Go path目录下,十分混乱。
为了解决这个问题(还是使用GoPath),我们就会每个工程都指定一个新的GoPath,这样看起来项目管理很清晰,大家都分开了。然而第三方库,你每次都要下载。
- GoVendor
通过命令启用govendor:
export GO15VENDOREXPEIMENT=1
效果是所有的依赖包都会下载到./vendor
目录下面。编译的时候也会使用目录下的依赖包,使用go vendor命令更新依赖包。这样子解决了依赖包和工程代码混杂的问题,但是没有解决多个工程代码之间混杂的问题。
- Go Mod
export GO111MODULE=on // 启用go mod
本质是使用go.mod文件来描述我们依赖库的名称和版本。下载的依赖会放在
$GOPAHT/pkg/mod文件夹下面
同时工程代码不一定要放在GOPATH下面。
但是在企业实践中,我们还是建议所有工程都放在GOPATH目录下,这样工程结构会比较清晰,也就是govendor其实和go mod效果差不多。
Go mod 如何工作的
- gomod版本的表达方式
- 语义化版本,也就是常见的v1.0.3这种形式
v${major}.${minor}.${patch}
major不同则认为是两个不同的仓库
- 伪版本号
可以基于某个commit来,比如我们常见:
xx/xxx/xxx v0.0.0-20210323104329-2dfsdfsdf
xx/xxx/xxx v0.0.0
-20210323104329
-2dfsdfsdf
基本版本前缀
commit utc时间
commit hash前12位
- 主要的命令
go get xxxx依赖库
- go get 依赖库可以跟上具体的commit hash 也可以跟上某个分支例如:
- go get 依赖库@hash
- go get 依赖库@master
go mod tidy // 自动添加或者删除项目依赖的库
- gomod 版本选择机制
问:x项目依赖a,b,a、b都依赖c项目,但是a依赖c的v1.1.1,b依赖c的v1.2.2,最后编译x的时候使用的c项目的版本是什么?
答案是最高版本v1.2.2。下图是Go mod的选择策略Minimal version selection (MVS)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qZZb16st-1624771950092)(/Users/bytedance/Library/Application Support/typora-user-images/image-20210626155846867.png)]
工程和依赖管理常见问题
-
在go mod文件中我们会看见一些标识:
- // indirect
此依赖不是本项目直接的依赖,但在本项目中指定该依赖。(a依赖b,b依赖c,在a中可以指定c是什么版本)
- // incompatible
该依赖未使用gomod管理依赖,不影响使用
-
一些工具
go mod graph :查看依赖之前的关系
go mod vendor: 把依赖的文件放在工程目录下的vendor文件夹中,类似go vendor。一般不用提交vendor下的文件,主要是用来查、跳转代码用的。
- 临时修改依赖库中的代码进行测试
git clone下来代码到本地,checkout对应版本,go mod文件中replace
业务实践中的经典案例
- go get -u 会拉取依赖的依赖,可能会导致一些意想不到的问题,建议不要加上-u
- 如果依赖没有使用mod,默认是拉取最新的版本;建议无论依赖有没有使用mod,我们的新项目都要用mod
- 依赖的a项目的tag删除了,该怎么办
- 如果只是你的项目,那么就重新go get,获取最新的版本
- 如果不仅是你的项目,而且你的依赖b也依赖这个a项目,那么就在你的项目上replace这个a项目。长期来看,还是要把你的依赖b重新go get一下。
- 如果你有一段公共代码,多个服务要调用,你会怎么办?
- rpc:更新内部逻辑的时候,无需调用方上线;屏蔽内部逻辑,接口定义明确;减少依赖的引入,避免保密级别代码泄漏(让我想到信贷的一些核心代码,不过它是在一个加密的包里面的,是二进制文件,我记得是,也保证了加密)
- sdk:成本低,引入后可以debug,稳定性好
最后
以上就是烂漫菠萝为你收集整理的Go工程管理和业务实践的全部内容,希望文章能够帮你解决Go工程管理和业务实践所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复