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



相关文章
|
3月前
|
Go 开发者
Go语言包的组织与导入 -《Go语言实战指南》
本章详细介绍了Go语言中的包(Package)概念及其使用方法。包是实现代码模块化、复用性和可维护性的核心单位,内容涵盖包的基本定义、命名规则、组织结构以及导入方式。通过示例说明了如何创建和调用包,并深入讲解了`go.mod`文件对包路径的管理。此外,还提供了多种导入技巧,如别名导入、匿名导入等,帮助开发者优化代码结构与可读性。最后以表格形式总结了关键点,便于快速回顾和应用。
193 61
|
2月前
|
JSON 中间件 Go
Go语言实战指南 —— Go中的反射机制:reflect 包使用
Go语言中的反射机制通过`reflect`包实现,允许程序在运行时动态检查变量类型、获取或设置值、调用方法等。它适用于初中级开发者深入理解Go的动态能力,帮助构建通用工具、中间件和ORM系统等。
239 63
|
1月前
|
缓存 监控 安全
告别缓存击穿!Go 语言中的防并发神器:singleflight 包深度解析
在高并发场景中,多个请求同时访问同一资源易导致缓存击穿、数据库压力过大。Go 语言提供的 `singleflight` 包可将相同 key 的请求合并,仅执行一次实际操作,其余请求共享结果,有效降低系统负载。本文详解其原理、实现及典型应用场景,并附示例代码,助你掌握高并发优化技巧。
201 0
|
4月前
|
Go 持续交付 开发者
Go语言包与模块(module)的基本使用-《Go语言实战指南》
本章深入讲解Go语言中的包(Package)和模块(Module)概念。包是代码组织的最小单位,每个`.go`文件属于一个包,通过`import`实现复用;主程序包需命名为`main`。模块是Go 1.11引入的依赖管理机制,支持自动版本管理和私有/远程仓库,无需依赖GOPATH。通过实际示例,如自定义包`mathutil`和第三方模块`gin`的引入,展示其使用方法。常用命令包括`go mod init`、`go mod tidy`等,帮助开发者高效管理项目依赖。最后总结,包负责功能划分,模块实现现代化依赖管理,提升团队协作效率。
222 15
|
7月前
|
算法 测试技术 Go
Go 1.24.0 重磅发布:新特性、新工具,开发者必看!
`Go 1.24.0` 已正式发布,带来诸多改进和新特性。语言层面上,泛型类型别名现已被完全支持;性能方面,通过优化 `map` 实现和内存分配,减少了 2-3% 的 CPU 开销;工具链新增模块工具依赖跟踪及测试分析器;标准库增加了弱引用包、FIPS 140-3 合规机制等;WebAssembly 支持也得到了增强。快来下载体验吧!
415 7
|
8月前
|
Go 数据库
Go语言中的包(package)是如何组织的?
在Go语言中,包是代码组织和管理的基本单元,用于集合相关函数、类型和变量,便于复用和维护。包通过目录结构、文件命名、初始化函数(`init`)及导出规则来管理命名空间和依赖关系。合理的包组织能提高代码的可读性、可维护性和可复用性,减少耦合度。例如,`stringutils`包提供字符串处理函数,主程序导入使用这些函数,使代码结构清晰易懂。
316 11
|
9月前
|
Linux Go iOS开发
怎么禁用 vscode 中点击 go 包名时自动打开浏览器跳转到 pkg.go.dev
本文介绍了如何在 VSCode 中禁用点击 Go 包名时自动打开浏览器跳转到 pkg.go.dev 的功能。通过将 gopls 的 `ui.navigation.importShortcut` 设置为 "Definition",可以实现仅跳转到定义处而不打开链接。具体操作步骤包括:打开设置、搜索 gopls、编辑 settings.json 文件并保存更改,最后重启 VSCode 使设置生效。
342 8
怎么禁用 vscode 中点击 go 包名时自动打开浏览器跳转到 pkg.go.dev
|
7月前
|
编译器 Go
揭秘 Go 语言中空结构体的强大用法
Go 语言中的空结构体 `struct{}` 不包含任何字段,不占用内存空间。它在实际编程中有多种典型用法:1) 结合 map 实现集合(set)类型;2) 与 channel 搭配用于信号通知;3) 申请超大容量的 Slice 和 Array 以节省内存;4) 作为接口实现时明确表示不关注值。此外,需要注意的是,空结构体作为字段时可能会因内存对齐原因占用额外空间。建议将空结构体放在外层结构体的第一个字段以优化内存使用。
|
7月前
|
运维 监控 算法
监控局域网其他电脑:Go 语言迪杰斯特拉算法的高效应用
在信息化时代,监控局域网成为网络管理与安全防护的关键需求。本文探讨了迪杰斯特拉(Dijkstra)算法在监控局域网中的应用,通过计算最短路径优化数据传输和故障检测。文中提供了使用Go语言实现的代码例程,展示了如何高效地进行网络监控,确保局域网的稳定运行和数据安全。迪杰斯特拉算法能减少传输延迟和带宽消耗,及时发现并处理网络故障,适用于复杂网络环境下的管理和维护。
|
1月前
|
数据采集 Go API
Go语言实战案例:多协程并发下载网页内容
本文是《Go语言100个实战案例 · 网络与并发篇》第6篇,讲解如何使用 Goroutine 和 Channel 实现多协程并发抓取网页内容,提升网络请求效率。通过实战掌握高并发编程技巧,构建爬虫、内容聚合器等工具,涵盖 WaitGroup、超时控制、错误处理等核心知识点。