Golang中的项目管理是对代码包的管理

引言

如果想要在项目中使用第三方代码库,C/C++ 中一般会有两种方法,

1. 将第三方源码合并到自己的工程文件中直接编译;

2. 将第三方代码先编译生成静态链接库(.a、.lib)或动态链接库(.so 、.dll) 放到工程目录下,然后通过条件编译直接使用。

目前大多数主流语言都有一套标准的包管理解决方案,比如 Java 有 maven,Python 有 pip,Ruby 有 RubyGems,Rust 有 Cargo,Nodejs 有 npm,PHP 有 composer。包管理工具用于自动化构建代码,以及使用一致的方式下载、更新和删除项目依赖项。

与 C/C++ 不同,Go 语言使用三方库的方式类似于依赖包管理,在编程时直接引入第三方库的地址,比如 Git 仓库,然后在编译的时候,IDE 会自动拉取第三方库文件到当前工程。对 Golang 项目的管理其实就是对代码包的管理。但是又和 npm、composer 等这些管理依赖的方式(composer-PHP包依赖管理工具)不同,比如 composer 的方式是中间借助了一个 php 的应用商店(packagist),它通过项目中定义的 composer.json 去下载依赖包,整个过程使用 composer 的命令行工具,命令行工具怎么知道有多少包可以被用户使用呢,那就是使用 packagist 作为包信息存储库,包开发者将具体代码托管到 Github 上,将包信息提交到 packagist 上,这样使用者就可以通过 composer 去使用,composer 本质上就是将 Github 上的代码下载到本地。具体做法是,composer 根据本地定义的composer.json 信息去查询 packagist,packagist 根据 composer.json/package.json 信息解析,最终对应到 Github 仓库,composer 最终下载代码的时候还要依赖于 Github 仓库上的composer.json,这里涉及到三种类型的 composer.json,含义是不一样的。packagist 相当于 composer 的默认的开发包仓库,项目下载依赖包就是从这个中心开发包仓库(应用商店)中下载依赖包来使用。packagist 目前的运作方式是可以将自己的安装包信息提交到 packagist,将来你在 Github 仓库中新建了 tag 或更新了代码,packagist 都会自动构建一个新的开发包,将来 packagist 将允许直接上传开发包,发布自己的包。

那么,Go 的包依赖管理呢?

正文

在 Go 语言早期的版本,包依赖管理是缺失的,后面也经历了一些混乱的时代。

根据 Go 的历史发布版本,Go 的包管理大致分成以下几个时间点和阶段,

go 尚未正式发布,goinstall(2010.02)

go 1,go get(2011.12)

go 1.2.1,gopkg.in(2014.03)

go 1.5,vendor 目录(2015.06)

go 1.8.3,官方出品 golang/dep(2017.05)

go 1.11,go module(2018.08)

go 1.13,go module 的改进(2019.08)

Golang 的包管理有两个特点,一个是去中心化,包的仓库可以是任意的代码仓库;一个是三方代码库跟项目代码本身耦合在一起,这个也是 Golang 推荐的工作方式。

在安装好 Go 后,配置环境变量时,可以选择性配置 GO111MODULE。比如

export GO111MODULE=auto

注意,这个变量是 Go 1.11 推出的,之后 Go 的不同版本,这个环境变量有不同的值含义。

如果 go mod 状态没有打开,可以使用 go env 找到自己的 GOPATH,在 GOPATH 下建立 src 目录,在 src 下建立自己的项目。这时记住一句话就行了,Go 找包都是去 GOPATH 下的 src 目录下找的,项目一定放在 GOPATH 的 src 目录下。一般 bin 和 pkg 目录可以不创建,go命令会自动创建(如 go install),只需要创建src目录即可,不过最好创建一下。

高版本的 Go 一般自带 go mod,go mod 是比 GOPATH 更新的一种 Go 包管理方式,使用了 go mod 后,就不需要把项目放在 GOPATH 下,Go 也能找到了。

当然,GOPATH 和 go mod 可以共存。

当 modules 功能启用时,依赖包的存放位置变更为 $GOPATH/pkg,允许同一个 package 多个版本并存,且多个项目可以共享缓存的 module。

使用 go mod 管理包

go mod 命令

go mod init 初始化一个项目

go mod download 下载依赖包,依赖包会自动下载到 $GOPATH/pkg/mod,多个项目可以共享缓存的mod

go mod tidy 拉取缺少的模块,移除不用的模块

go mod verify 验证依赖是否正确

go mod vendor 从mod中拷贝到项目的vendor目录下,这样IDE就可以识别了

go mod why 解释为什么需要依赖

go mod 为项目引入依赖

执行 go mod init 命令,初始化一个项目,会在项目根目录下生成 go.mod 文件。

go mod init github.com/project

go.mod 提供了 module、require、replace 和 exclude 四个命令。

  • module 语句指定包的名字(路径)
  • require 语句指定的依赖项模块
  • replace 语句可以替换依赖项模块
  • exclude 语句可以忽略依赖项模块

假如需要引入 protobuf,添加 require,可以手动修改 go.mod 文件增加依赖,或者让 go 自动发现和维护,最好使用 go get 命令(不同的 Go 版本,go get的行为会有不同,一般默认会将下载(源码包)和安装(go install)合并起来,当然你也可以通过参数指定将拆散它们)。

// 手动修改 eg.
go mod init .
go mod edit -require github.com/golang/protobuf@1.5.0` 
go get -v -t ./...   
go build
go install 

注意,如果在后续模块代码编写时 import 了该模块,但没有在 go.mod 中引用它,在执行 go build 时就会报错,但执行 build 后依赖包会记录在 go.mod 中,这时执行 go mod download,或 go mod tidy 就可以了。

go get github.com/golang/protobuf
或
go get github.com/golang/protobuf@v1.5.0

这条命令执行完之后,在 go.mod 中会添加如下语句,同时生成 go.sum 文件,依赖包被下载到 $GOPATH/pkg/mod 中。这时就可以在项目中使用了。go get 指定版本_29. 系统学习 Go语言命令_weixin_39611043的博客-CSDN博客

go.mod(通过这个文件管理包)

go.sum 文件(一般不需要手工维护)

包含特定模块版本内容的预期加密哈希,Go 命令使用 go.sum 文件确保这些模块的未来下载检索与第一次下载相同的位,以确保项目所依赖的模块不会出现意外更改,无论是出于恶意、意外还是其他原因。 go.mod 和 go.sum 都应检入版本控制。 

注意:子目录里是不需要 init 的,所有的子目录里的依赖都会组织在根目录的 go.mod 文件里。

如果要在 IDE 中查看,还需执行 go mod vendor

go mod vendor

go mod vendor 还有一个作用,一般第三方依赖库(包括公司内网 GitLab 上的依赖库),其源码都不被包含在我们的项目内部,而是在编译的时候 Go 连接公网、内网下载到本地 GOPATH,然后编译。问题是,有时候需在无公网、无内网(无法连接内网 GitLab)的情况下编译 go 项目,或者由于种种原因,比如

  1. 防止依赖库因为某种原因被删除、移动,导致找不到依赖并编译失败;
  2. 对新手来说,下载一些墙外的依赖可能略有困难;

该如何做呢?在此时,需使用 go mod vendor 将项目的依赖库下载到项目内部,作为项目的一部分来编译。

https://golang.org/ref/mod#go-mod-vendor

https://golang.org/ref/mod#vendoring

Have Fun

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值