Go:包管理工具GOPATH、vendor、dep 、go module

简介: Go:包管理工具GOPATH、vendor、dep 、go module

目录

Go包管理工具:前言

GOPATH

vendor、dep

Go modules

Module 文件

go mod命令

Go modules使用步骤:

go module的文件下载后位置:



Go包管理工具:前言

Golang一直存在一个被人诟病的问题是缺少一个官方的包依赖管理工具。从我个人的角度上来看存在两个问题:

  1. GOPATH特性对于多工程的情况下,支持不算友好。
  2. GOPATH无法对依赖包进行有效的版本管理,没有任何地方能够表明依赖包的具体版本号,无法简单清晰获取到有效的依赖包版本信息等。


GOPATH

GOPATH

1. 在 1.8 版本前必须设置这个环境变量

2. 1.8 版本后(含 1.8)如果没有设置使⽤用默认值

  • 在 Unix 上默认为 $HOME/go , 在 Windows 上默认为 %USERPROFILE%/go
  • 在 Mac 上 GOPATH 可以通过修改 ~/.bash_profile 来设置

在 go mod 出现之前,所有的 Go 项目都需要放在同一个工作空间:$GOPATH/src 内,比如:

src/
    github.com/golang/example/
        .git/                      # Git repository metadata
    outyet/
        main.go                # command source
        main_test.go           # test source
    stringutil/
        reverse.go             # package source
        reverse_test.go        # test source

相比其他语言,这个限制有些无法理解。其实,这和 Go 的一设计理念紧密相关:

包管理应该是去中心化的


所以 Go 里面没有 maven/npm 之类的包管理工具只有一个 go get,支持从公共的代码托管平台(Bitbucket/GitHub..)下载依赖,当然也支持自己托管,具体可参考官方文档:Remote import paths


由于没有中央仓库,所以 Go 项目位置决定了其 import path,同时为了与 go get 保持一致,所以一般来说我们的项目名称都是 github.com/user/repo 的形式。

当然也可以不是这种形式,只是不方便别人引用而已,后面会讲到如何在 go mod 中实现这种效果


vendor、dep

使用 go get 下载依赖的方式简单暴力,伴随了 Go 七年之久,直到 1.6(2016/02/17)才正式支持了 vendor,可以把所有依赖下载到当前项目中,解决可重复构建(reproducible builds)的问题,但是无法管理依赖版本。社区出现了各式各样的包管理工具,来方便开发者固化依赖版本,由于不同管理工具采用不同的元信息格式(比如:godep 的 Godeps.json、Glide 的 glide.yaml),不利于社区发展,所以 Go 官方推出了 dep

dep 的定位是实验、探索如何管理版本,并不会直接集成到 Go 工具链,Go 核心团队会吸取 dep 使用经验与社区反馈,开发下一代包管理工具 modules,并于 2019/09/03 发布的 1.13 正式支持,并随之发布 Module Mirror, Index, Checksum,用于解决软件分发、中间人攻击等问题。下图截取自 Go 官方博客

Module Big Picture


Go modules

Go modules机制在go 1.11中是experiment feature,按照Go的惯例,在新的experiment feature首次加入时,都会有一个特性开关,go modules也不例外,GO111MODULE这个临时的环境变量就是go module特性的experiment开关。

GO111MODULE有三个值:auto、on和off,默认值为auto。

GO111MODULE的值会直接影响Go compiler的“依赖管理”模式的选择(是GOPATH mode还是module-aware mode),我们详细来看一下:

  • 当GO111MODULE的值为off时,go modules experiment feature关闭,go compiler显然会始终使用GOPATH mode,即无论要构建的源码目录是否在GOPATH路径下,go compiler都会在传统的GOPATH和vendor目录(仅支持在gopath目录下的package)下搜索目标程序依赖的go package;
  • 当GO111MODULE的值为on时(export GO111MODULE=on),go modules experiment feature始终开启,与off相反,go compiler会始终使用module-aware mode,即无论要构建的源码目录是否在GOPATH路径下,go compiler都不会在传统的GOPATH和vendor目录下搜索目标程序依赖的go package,而是在go mod命令的缓存目录($GOPATH/pkg/mod)下搜索对应版本的依赖package
  • 当GO111MODULE的值为auto时(不显式设置即为auto),也就是我们在上面的例子中所展现的那样:使用GOPATH mode还是module-aware mode,取决于要构建的源码目录所在位置以及是否包含go.mod文件
  • 如果要构建的源码目录不在以GOPATH/src为根的目录体系下,且包含go.mod文件(两个条件缺一不可),那么使用module-aware mode;
  • 否则使用传统的GOPATH mode。


Module 文件

执行命令 go build && go mod tidy ,下载依赖并整理。

项目根目录下会生成两个文件(需要加入到 git 中):

  • 文件 go.mod:指示模块名称、go 的版本、该模块的依赖信息(依赖名称),类似 npm 生成的文件 package.json
  • 文件 go.sum:该模块的所有依赖的校验和,类似 npm 生成的文件 package-lock.json

Module 是多个 package 的集合,版本管理的基本单元,使用 go.mod 文件记录依赖的 module。

go.mod 位于项目的根目录,支持 4 条命令:module、require、replace、exclude。示例:

module github.com/my/repo
require (
    github.com/some/dependency v1.2.3
    github.com/another/dependency/v4 v4.0.0
)
  • module 声明 module path,一个 module 内所有 package 的 import path 都以它为前缀
  • require 声明所依赖的 module,版本信息使用形如 v(major).(minor).(patch) 的语义化版本
  • replace/exclude 用于替换、排查指定 module path


go mod命令

golang 提供了 go mod命令来管理包。

go mod 有以下命令:

命令 说明
download download modules to local cache(下载依赖包)
edit edit go.mod from tools or scripts(编辑go.mod)
graph print module requirement graph (打印模块依赖图)
init initialize new module in current directory(在当前目录初始化mod)
tidy add missing and remove unused modules(拉取缺少的模块,移除不用的模块)
vendor make vendored copy of dependencies(将依赖复制到vendor下)
verify verify dependencies have expected content (验证依赖是否正确)
why explain why packages or modules are needed(解释为什么需要依赖)


Go modules使用步骤:

  1. 首先将你的版本更新到最新的Go版本(>=1.11)。
  2. 通过go命令行,进入到你当前的工程目录下,在命令行设置环境变量
#方式1:临时设置
注意
# Windows环境用set
# linux环境用export
#########Windows#########
# 开启
set GO111MODULE=on
# 1.13 之后才支持多个地址,之前版本只支持一个
set GOPROXY=https://goproxy.cn,https://mirrors.aliyun.com/goproxy,direct
# 1.13 开始支持,配置私有 module,不去校验 checksum
set GOPRIVATE=*.corp.example.com,rsc.io/private
#########Linux#########
# 开启
export GO111MODULE=on
# 1.13 之后才支持多个地址,之前版本只支持一个
export GOPROXY=https://goproxy.cn,https://mirrors.aliyun.com/goproxy,direct
# 1.13 开始支持,配置私有 module,不去校验 checksum
export GOPRIVATE=*.corp.example.com,rsc.io/private
#方式2:全局设置
# 设置全局开启 go mod Go1.16版本默认为on,可跳过这一步
go env -w GO111MODULE=on 
# 设置全局代理地址
go env -w GOPROXY=https://goproxy.cn,https://mirrors.aliyun.com/goproxy,direct 
  1. 执行命令go mod init在当前目录下生成一个go.mod文件,执行这条命令时,当前目录不能存在go.mod文件。如果之前生成过,要先删除;
  2. 如果你工程中存在一些不能确定版本的包,那么生成的go.mod文件可能就不完整,因此继续执行下面的命令;
  3. 执行go mod tidy命令,它会添加缺失的模块以及移除不需要的模块。执行后会生成go.sum文件(模块下载条目)。添加参数-v,例如go mod tidy -v可以将执行的信息,即删除和添加的包打印到命令行;
  4. 执行命令go mod verify来检查当前模块的依赖是否全部下载下来,是否下载下来被修改过。如果所有的模块都没有被修改过,那么执行这条命令之后,会打印all modules verified。
  5. 执行命令go mod vendor生成vendor文件夹,该文件夹下将会放置你go.mod文件描述的依赖包,文件夹下同时还有一个文件modules.txt,它是你整个工程的所有模块。在执行这条命令之前,如果你工程之前有vendor目录,应该先进行删除。同理go mod vendor -v会将添加到vendor中的模块打印出来;


go module的文件下载后位置:

存储下载的依赖包,具体位置在$GOPATH/pkg/mod

在 Go 1.8 版本之前,GOPATH 环境变量默认是空的。从 Go 1.8 版本开始,Go 开发包在安装完成后,将 GOPATH 赋予了一个默认的目录,参见下表。

GOPATH 在不同平台上的安装路径

平  台 GOPATH 默认值 举 例
Windows 平台 %USERPROFILE%/go C:\Users\用户名\go
Unix 平台 $HOME/go /home/用户名/go

代理地址

https://goproxy.cn  //七牛云赞助支持的开源代理

https://mirrors.aliyun.com/goproxy  //阿里云官方维护的go代理

https://goproxy.io //也是一个开源的go代理


参考链接:

何处安放我们的 Go 代码 - Keep Coding

初窥Go module | Tony Bai

golang module 开发基本流程 | 生活的自留地

research!rsc: Go & Versioning



相关文章
|
4月前
|
Go 开发者
Go语言包的组织与导入 -《Go语言实战指南》
本章详细介绍了Go语言中的包(Package)概念及其使用方法。包是实现代码模块化、复用性和可维护性的核心单位,内容涵盖包的基本定义、命名规则、组织结构以及导入方式。通过示例说明了如何创建和调用包,并深入讲解了`go.mod`文件对包路径的管理。此外,还提供了多种导入技巧,如别名导入、匿名导入等,帮助开发者优化代码结构与可读性。最后以表格形式总结了关键点,便于快速回顾和应用。
214 61
|
16天前
|
Java 编译器 Go
【Golang】(1)Go的运行流程步骤与包的概念
初次上手Go语言!先来了解它的运行流程吧! 在Go中对包的概念又有怎样不同的见解呢?
54 4
|
3月前
|
JSON 中间件 Go
Go语言实战指南 —— Go中的反射机制:reflect 包使用
Go语言中的反射机制通过`reflect`包实现,允许程序在运行时动态检查变量类型、获取或设置值、调用方法等。它适用于初中级开发者深入理解Go的动态能力,帮助构建通用工具、中间件和ORM系统等。
266 63
|
2月前
|
缓存 监控 安全
告别缓存击穿!Go 语言中的防并发神器:singleflight 包深度解析
在高并发场景中,多个请求同时访问同一资源易导致缓存击穿、数据库压力过大。Go 语言提供的 `singleflight` 包可将相同 key 的请求合并,仅执行一次实际操作,其余请求共享结果,有效降低系统负载。本文详解其原理、实现及典型应用场景,并附示例代码,助你掌握高并发优化技巧。
250 0
|
5月前
|
Go 持续交付 开发者
Go语言包与模块(module)的基本使用-《Go语言实战指南》
本章深入讲解Go语言中的包(Package)和模块(Module)概念。包是代码组织的最小单位,每个`.go`文件属于一个包,通过`import`实现复用;主程序包需命名为`main`。模块是Go 1.11引入的依赖管理机制,支持自动版本管理和私有/远程仓库,无需依赖GOPATH。通过实际示例,如自定义包`mathutil`和第三方模块`gin`的引入,展示其使用方法。常用命令包括`go mod init`、`go mod tidy`等,帮助开发者高效管理项目依赖。最后总结,包负责功能划分,模块实现现代化依赖管理,提升团队协作效率。
233 15
|
9月前
|
Go 数据库
Go语言中的包(package)是如何组织的?
在Go语言中,包是代码组织和管理的基本单元,用于集合相关函数、类型和变量,便于复用和维护。包通过目录结构、文件命名、初始化函数(`init`)及导出规则来管理命名空间和依赖关系。合理的包组织能提高代码的可读性、可维护性和可复用性,减少耦合度。例如,`stringutils`包提供字符串处理函数,主程序导入使用这些函数,使代码结构清晰易懂。
329 11
|
10月前
|
Linux Go iOS开发
怎么禁用 vscode 中点击 go 包名时自动打开浏览器跳转到 pkg.go.dev
本文介绍了如何在 VSCode 中禁用点击 Go 包名时自动打开浏览器跳转到 pkg.go.dev 的功能。通过将 gopls 的 `ui.navigation.importShortcut` 设置为 "Definition",可以实现仅跳转到定义处而不打开链接。具体操作步骤包括:打开设置、搜索 gopls、编辑 settings.json 文件并保存更改,最后重启 VSCode 使设置生效。
384 8
怎么禁用 vscode 中点击 go 包名时自动打开浏览器跳转到 pkg.go.dev
|
NoSQL Go 开发工具
《快学 Go 语言》第 16 课 —— 包管理 GOPATH 和 Vendor
到目前位置我们一直在编写单文件代码,只有一个 main.go 文件。本节我们要开始朝完整的项目结构迈进,需要使用 Go 语言的模块管理功能来组织很多的代码文件。 细数 Go 语言的历史发展,模块管理经历了三个重要的阶段。
3481 0
|
16天前
|
存储 安全 Java
【Golang】(4)Go里面的指针如何?函数与方法怎么不一样?带你了解Go不同于其他高级语言的语法
结构体可以存储一组不同类型的数据,是一种符合类型。Go抛弃了类与继承,同时也抛弃了构造方法,刻意弱化了面向对象的功能,Go并非是一个传统OOP的语言,但是Go依旧有着OOP的影子,通过结构体和方法也可以模拟出一个类。
68 1
|
2月前
|
Cloud Native 安全 Java
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
254 1

热门文章

最新文章