Go Modules
什么是 module
A module is a collection of related Go packages that are versioned together as a single unit.
Modules record precise dependency requirements and create reproducible builds.
Most often, a version control repository contains exactly one module defined in the repository root. (Multiple modules are supported in a single repository, but typically that would result in more work on an on-going basis than a single module per repository).
Summarizing the relationship between repositories, modules, and packages:
- A repository contains one or more Go modules.
- Each module contains one or more Go packages.
- Each package consists of one or more Go source files in a single directory.
Modules must be semantically versioned according to semver, usually in the form v(major).(minor).(patch), such as v0.1.0, v1.2.3, or v1.5.0-rc.1. The leading v is required. If using Git, tag released commits with their versions. Public and private module repositories and proxies are becoming available (see FAQ below).
module 是包和依赖的组合,目的是为了记录精确的依赖要求并创建可复制的构建
module 版本
- 语义版本 v(major).(minor).(patch)
- major:主版本,不同的主版本不兼容,例如 v2.1.1 与 v1.1.1 不兼容
- minor:次版本
- patch:修订版本
版本需要 VCS ,如果使用 git,则使用 tag 来管理版本
如何使用 gomod
在 project下 新建 go.mod 文件即可
cd ${project_path} && go mod init && go mod tidy
module_name 和 import 关联,举例:如果你的 module_name 为 example.com/mymod ,那么在Go源代码中,将使用 module_name 导入软件包mymod import "example.com/mymod"
go mod 命令
go mod help # 查看帮助
go mod init # 初始化新 module,module名称为包名
go mod init <module_name> # 初始化新 module,module名称为 module_name
go mod tidy # 删除不用的 module,拉取需要的 module,如果要 module 没有在 go.mod 中 require,则拉取最新版本,下载保存路径为 $GOPATH/pkg/mod/
go mod vender #生成vendor文件夹,并拷贝依赖到vendor中
go get -u example.com/package #使用最新的次要版本或修补程序版本(并添加-t以升级测试依赖项),在模块根目录中运行
Goland 使用 gomod
- 只要存在 go.mod 即可使用 gomod 方式运行
- 如果在
Preference
–Go
–Go Modules(vgo)
开启 Enable Go Modules (vgo) integeration,则所有的项目强制使用 gomod
go.mod 文件
go.mod
module ${module_name}/${module_version}
go ${go_version}
require ${module_name} v${module_version}
replace ${module_name} => ${local_path}
示例
module util
go 1.13
require (
github.com/beevik/guid v0.0.0-20170504223318-d0ea8faecee0
github.com/go-sql-driver/mysql v1.5.0
github.com/tealeg/xlsx v1.0.5
golang.org/x/text v0.3.2
)
注:在一些博客上看到 module 的名字最好是 域名/模块名,否则 go 1.13 是不通过的,没有重现
require 指定 module 的名称以及版本,如果你不知道什么版本在使用require
指令,你可以使用v0.0.0
如require foo v0.0.0
replace 指令允许您提供另一个导入路径,该路径可能是VCS(GitHub或其他地方)中的另一个模块,或者是本地文件系统上的另一个模块
replace example.com/some/dependency => example.com/some/dependency v1.2.3
replace example.com/some/dependency => example.com/some/dependency-fork v1.2.3
replace example.com/original/import/path => /your/forked/import/path
replace example.com/project/foo => ../foo
gomod 配置
以下问题在运行环境 GoLand2019.3 go1.13测试通过
-
对某些私有 module 跳过 GOPROXY 代理
go env -w GOPROXY=https://goproxy.io,direct # 设置不走 proxy 的私有仓库,多个用逗号相隔 go env -w GOPRIVATE=*.core.example.com
-
如何自动配置 go.mod
cd /$project && go mod tidy
go mod tidy
对本地 module 无效 -
如何引用本地 module
例如:util, base 为本地包, util 引用 base,文件结构如下
├─util │ util.go │ go.mod ├─base │ go.mod │ base.go
-
/base 必须也被 gomod (含 go.mod文件)
/base/go.mod
module base go 1.13
-
修改 /util/go.mod
module util go 1.13 require base v0.0.0 replace base => ../base
-
-
A,B,C 均为本地module,A 引用 B ,B 又引用 C
举例:serv 引用本地包 util, util 引用本地包 base,文件结构如下
├─serv │ serv.go │ go.mod ├─util │ util.go │ go.mod ├─base │ go.mod │ base.go
如果按照上一个问题"如何引用本地 module"来配置,也就是 util 引用 base, serv 在引用 util,是运行不起来的,必须要在 serv 的 go.mod require 和 replace util包引用的base包
/serv/go.mod
module serv go 1.13 require util v0.0.0 replace util => ../util require base v0.0.0 replace base => ../base
https://github.com/golang/go/wiki/Modules ↩︎