go的包管理与环境变量
参考:深入理解 Go Modules 的 go.mod 与 go.sum
Go Module详细使用教程
使用Go env命令设置Go的环境
包管理总结:
- go.mod存储着依赖的模块和模块的版本,如果模块不存在,可以使用
go mod tidy
自动去下载。模块一般全部放在GOPATH下面,当然我们也可以建立一个vendor 目录,将所有依赖的模块放在vendor 目录中。
module(包名,一般为github仓库连接)、require(必须要下载的包)、replace(替换为本地包)、exclude(排除某些依赖项的版本)
go.sum则是记录了所有依赖的 module 的校验信息 - 版本号:一般在github等远程仓库中编写。
1.go的包管理
go的三种包管理方式:
- GOPATH:所有项目的依赖包全部放在GOPATH下面
- vendor:每个项目下可以有一个 vendor 目录,里面存放了该项目的依赖的package。go build 的时候会先去vendor目录查找依赖,如果没有找到会再去 GOPATH 目录下查找。缺点:不能指定依赖包的版本,不能回退版本。
- Modules:每个Modules下面有go.mod 和 go.sum,go.mod 文件定义依赖库的版本,go.sum包含特定依赖包的版本内容的散列哈希值。一般我们项目都是单module的形式,项目主文件夹下包含go.mod,子文件夹定义package,或者主文件夹也是一个package。但是一个项目也可以包含多个module,只不过这种方式不常用而已。下载的依赖包放到GOPATH/pkg/mod目录下。
下面介绍一下go.mod 和 go.sum。
版本号
首先我们了解一下版本号:major.minor.patch-tag+metadata,比如v1.3.0、v2.0.0-alpha.1 等等。
- 主版本号(major):当你做了不兼容的API修改,
- 次版本号(minor):当你做了向下兼容的功能性新增,
- 修订号(patch):当你做了向下兼容的问题修正。
- tag如果你想为你的项目发版,你可以设置tag为上面的格式,比如v2.0.0-beta。
- metadata中在Go版本比较时是不参与运算的,只是一个辅助信息。
tag是在github等远程仓库中设置的,可以参考如下:Golang开源发布自己的包
go.mod与go.sum
go.mod用来标记一个 module 和它的依赖库以及依赖库的版本,支持 4 条命令:module、require、replace、exclude。下面是一个go.mod的实例说明:
module github.com/dablelv/go-huge-util // 模块名称,这是模块的唯一标识符,其他模块可以使用这个名称引用该模块提供的包。
// 如go mod init example.com/hello就会生成名为example.com/hello的模块名称,
// 注意:没有在当前目录下生成example.com/hello目录。
// 如果你的版本已经 >=2.0.0,则应该改为module github.com/dablelv/go-huge-util/v2
go 1.17 // 代码所需要的 Go 的最低版本。
// 将 github.com/coreos/bbolt 这个模块替换成本地路径为 ../r 的模块。
// 让 Go 编译器在开发期间直接使用本地的修改过的代码,而不是下载远程仓库中的代码。
// 这个指令只会影响开发者本地的编译和调试,而不会影响依赖模块在其他环境中的编译和部署。
// 因此,当开发完成后,需要将 replace 指令移除,以确保在生产环境中使用的是远程仓库中的代码。
replace github.com/coreos/bbolt => ../r
require ( // 各个依赖库以及它们的版本
github.com/cenk/backoff v2.2.1+incompatible // incompatible:代表不符合 Go 的 module 管理规范。版本已经 >=2 了,
// 但是他们的 module path 中依然没有添加 v2、v3 这样的后缀,不符合 Go 的 module 管理规范。
github.com/edwingeng/doublejump v0.0.0-20200330080233-e4ea8bd1cbed // 本库未生成版本号,所以这里自动生成了一个v0.0.0-20200330080233-e4ea8bd1cbed
// 20200330080233-e4ea8bd1cbed=提交的时间+commit id。通过这个字段,就可以确定这个库的特定的版本。
github.com/go-sql-driver/mysql v1.5.0
github.com/spf13/cast v1.4.1
github.com/stretchr/testify v1.7.0
golang.org/x/text v0.3.2
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect // 有indirect注释的,代表间接使用到的库
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
)
exclude ( // exclude用于排除一个特定的版本或版本范围的依赖项
go.etcd.io/etcd/client/v2 v2.305.0-rc.0
go.etcd.io/etcd/client/v3 v3.5.0-rc.0
)
// retract用于撤回一个特定的版本或版本范围的依赖项。当你在你的项目中使用的依赖项与你依赖的
// 其他依赖项不兼容时,可以使用retract关键字来撤回依赖项。
// 例如,如果你想撤回版本号为v1.2.3的依赖项,可以添加以下行:
retract (
github.com/user/repo v1.2.3
)
go.sum则是记录了所有依赖的 module 的校验信息,以防下载的依赖被恶意篡改,主要用于安全校验。
go mod 命令
The commands are:
download download modules to local cache (下载依赖的module到本地cache))
edit edit go.mod from tools or scripts (编辑go.mod文件)
graph print module requirement graph (打印模块依赖图))
init initialize new module in current directory (再当前文件夹下初始化一个新的module, 创建go.mod文件))
tidy add missing and remove unused modules (增加丢失的module,去掉未用的module)
vendor make vendored copy of dependencies (将依赖复制到vendor下)
verify verify dependencies have expected content (校验依赖)
why explain why packages or modules are needed (解释为什么需要依赖)
2. go的环境变量介绍
1.GOPATH:在 go mod 出现之前,所有的 Go 项目都需要放在同一个工作空间:$GOPATH/src 内
2.GO111MODULE有三个值:off、on 和 auto(默认值)。
- GO111MODULE=off,无模块支持,go 会从 GOPATH 和 vendor 文件夹寻找包
- GO111MODULE=on,模块支持,go 会忽略 GOPATH 和 vendor 文件夹,只根据 go.mod 下载依赖。在使用
Modules
模式的时候,GOPATH 是无意义的,不过它还是会把下载的依赖储存在$GOPATH/pkg/mod
中,也会把go install
的结果放在$GOPATH/bin
中。
还可以使用go mod vendor
将依赖复制到当前模块的vendor目录下 - GO111MODULE=auto,可以使用GOPATH,也可以使用go.mod来管理包。
注: 推荐将 GO111MODULE 设置为on 而不是auto
3.GOPROXY
由于中国政府的网络监管系统,Go 生态系统中有着许多中国 Gopher 们无法获取的模块,比如最著名的 golang.org/x/...。并且在中国大陆从 GitHub 获取模块的速度也有点慢。因此需要配置GOPROXY来加速Module依赖下载,这里使用goproxy.cn代理,
Go 1.13及以上版本:go env -w GOPROXY=https://goproxy.cn,direct
Go 1.13以下的版本:export GOPROXY=https://goproxy.cn
go环境变量的修改
通过go env
可查看go现有的环境变量,通过类似如下方式可以修改环境变量:
export GO111MODULE=on
export GOPROXY=https://goproxy.io
当你安装的GO的语言版本大于1.13的时候,那么就不用这么麻烦了,直接使用go env -w命令就行了
go env -w GOPROXY=https://goproxy.io,direct
# Set environment variable allow bypassing the proxy for selected modules
go env -w GOPRIVATE=*.corp.example.com
go env -w GO111MODULE=on
这个我试过,即使你关闭了终端,新打开,还是可以的,这个命令比较的无伤害.
【修改GO111MODULE时的错误】warning: go env -w GO111MODULE=... does not override conflicting OS environment variable
原因:在设置的时候,系统的环境变量GO111MODULE已经有值,而go env是不支持覆盖写入的。但是可以修改系统文件.bash_profile 或者直接操作系统环境变量,如export GO111MODULE=off
3.导入包
导入包的注意点
module名为helloworld的目录结构如下(module名和此文件夹的名字应该可以不一样):
├── api
│ └── apis.go
└── server.go
server.go中不能这样导入api:
import (
api "./api" // 这里使用的是相对路径
)
只能这样导入api:
import (
api "helloworld/api" // 这是更新后的引入方法
)