Go语言go mod包依赖管理工具使用详解
模块是相关 Go 包的集合。modules 是源代码交换和版本控制的单元。go 命令直接支持使用 modules,包括记录和解析对其他模块的依赖性。modules 替换旧的基于 GOPATH 的方法来指定在给定构建中使用哪些源文件。
如何使用 Modules?
1) 首先需要把 golang 升级到 1.11(现在 1.12 已经发布了,建议使用 1.12)2) 设置 GO111MODULE
GO111MODULE
GO111MODULE 有三个值:off, on 和 auto(默认值)。- GO111MODULE=off,go 命令行将不会支持 module 功能,寻找依赖包的方式将会沿用旧版本那种通过 vendor 目录或者 GOPATH 模式来查找。
- GO111MODULE=on,go 命令行会使用 modules,而一点也不会去 GOPATH 目录下查找。
-
GO111MODULE=auto,默认值,go 命令行将会根据当前目录来决定是否启用 module 功能。这种情况下可以分为两种情形:
- 当前目录在 GOPATH/src 之外且该目录包含 go.mod 文件
- 当前文件在包含 go.mod 文件的目录下面。
当 modules 功能启用时,依赖包的存放位置变更为 $GOPATH/pkg,允许同一个 package 多个版本并存,且多个项目可以共享缓存的 module。
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 (解释为什么需要依赖) |
如何在项目中使用
【示例 1】创建一个新项目1) 在 GOPATH 目录之外新建一个目录,并使用
go mod init
初始化生成 go.mod 文件
~ mkdir hello
~ cd hello
hello go mod init hello
go: creating new go.mod: module hello
hello ls
go.mod
hello cat go.mod
module hello
go 1.12
go.mod 提供了 module, require、replace 和 exclude 四个命令
- module 语句指定包的名字(路径)
- require 语句指定的依赖项模块
- replace 语句可以替换依赖项模块
- exclude 语句可以忽略依赖项模块
2) 添加依赖
新建一个 server.go 文件,写入以下代码:
package main import ( "net/http" "github.com/labstack/echo" ) func main() { e := echo.New() e.GET("/", func(c echo.Context) error { return c.String(http.StatusOK, "Hello, World!") }) e.Logger.Fatal(e.Start(":1323")) }执行
go run server.go
运行代码会发现 go mod 会自动查找依赖自动下载:
$ go run server.go
go: finding github.com/labstack/echo v3.3.10+incompatible
go: downloading github.com/labstack/echo v3.3.10+incompatible
go: extracting github.com/labstack/echo v3.3.10+incompatible
go: finding github.com/labstack/gommon/color latest
go: finding github.com/labstack/gommon/log latest
go: finding github.com/labstack/gommon v0.2.8
# 此处省略很多行
...
____ __
/ __/___/ / ___
/ _// __/ _ \/ _ \
/___/\__/_//_/\___/ v3.3.10-dev
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
O\
⇨ http server started on [::]:1323
$ cat go.mod
module hello
go 1.12
require (
github.com/labstack/echo v3.3.10+incompatible // indirect
github.com/labstack/gommon v0.2.8 // indirect
github.com/mattn/go-colorable v0.1.1 // indirect
github.com/mattn/go-isatty v0.0.7 // indirect
github.com/valyala/fasttemplate v1.0.0 // indirect
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a // indirect
)
$ cat go.sum
github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg=
github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s=
github.com/labstack/gommon v0.2.8 h1:JvRqmeZcfrHC5u6uVleB4NxxNbzx6gpbJiQknDbKQu0=
github.com/labstack/gommon v0.2.8/go.mod h1:/tj9csK2iPSBvn+3NLM9e52usepMtrd5ilFYA+wQNJ4=
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
... 省略很多行
go run server.go
发现跳过了检查并安装依赖的步骤。可以使用命令
go list -m -u all
来检查可以升级的 package,使用 go get -u need-upgrade-package
升级后会将新的依赖版本更新到 go.mod * 也可以使用 go get -u 升级所有依赖go get 升级有一下几种方法:
- 运行 go get -u 将会升级到最新的次要版本或者修订版本(x.y.z, z 是修订版本号,y 是次要版本号)
- 运行 go get -u=patch 将会升级到最新的修订版本
- 运行 go get package@version 将会升级到指定的版本号 version
- 运行 go get 如果有版本的更改,那么 go.mod 文件也会更改
【示例 2】改造现有项目 (helloword)
项目目录为:
$ tree
.
├── api
│ └── apis.go
└── server.go
1 directory, 2 files
package main import ( api "./api" // 这里使用的是相对路径 "github.com/labstack/echo" ) func main() { e := echo.New() e.GET("/", api.HelloWorld) e.Logger.Fatal(e.Start(":1323")) }api/apis.go 源码为:
package api import ( "net/http" "github.com/labstack/echo" ) func HelloWorld(c echo.Context) error { return c.JSON(http.StatusOK, "hello world") }1) 使用
go mod init ***
初始化 go.mod
$ go mod init helloworld
go: creating new go.mod: module helloworld
go run server.go
go: finding github.com/labstack/gommon/color latest
go: finding github.com/labstack/gommon/log latest
go: finding golang.org/x/crypto/acme/autocert latest
go: finding golang.org/x/crypto/acme latest
go: finding golang.org/x/crypto latest
build command-line-arguments: cannot find module for path _/home/gs/helloworld/api
build command-line-arguments: cannot find module for path _/home/gs/helloworld/api
但是 go.mod 已经更新:
$ cat go.mod
module helloworld
go 1.12
require (
github.com/labstack/echo v3.3.10+incompatible // indirect
github.com/labstack/gommon v0.2.8 // indirect
github.com/mattn/go-colorable v0.1.1 // indirect
github.com/mattn/go-isatty v0.0.7 // indirect
github.com/valyala/fasttemplate v1.0.0 // indirect
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a // indirect
)
这是因为 server.go 中使用 internal package 的方法跟以前已经不同了,由于 go.mod 会扫描同工作目录下所有 package 并且变更引入方法,必须将 helloworld 当成路径的前缀,也就是需要写成 import helloworld/api,以往 GOPATH/dep 模式允许的 import ./api 已经失效,详情可以查看这个 issue。
3) 更新旧的 package import 方式
所以 server.go 需要改写成:
package main import ( api "helloworld/api" // 这是更新后的引入方法 "github.com/labstack/echo" ) func main() { e := echo.New() e.GET("/", api.HelloWorld) e.Logger.Fatal(e.Start(":1323")) }
4) 到这里就和新创建一个项目没什么区别了一个小坑:开始在 golang1.11 下使用 go mod 遇到过 go build github.com/valyala/fasttemplate: module requires go 1.12 这种错误,遇到类似这种需要升级到 1.12 的问题,直接升级 golang1.12 就好了。
使用 replace 替换无法直接获取的 package
由于某些已知的原因,并不是所有的package都能成功下载,比如:golang.org 下的包。modules 可以通过在 go.mod 文件中使用 replace 指令替换成 github 上对应的库,比如:
replace (
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a => github.com/golang/crypto v0.0.0-20190313024323-a1f597ede03a
)
replace golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a => github.com/golang/crypto v0.0.0-20190313024323-a1f597ede03a
所有教程
- socket
- Python基础教程
- C#教程
- MySQL函数
- MySQL
- C语言入门
- C语言专题
- C语言编译器
- C语言编程实例
- GCC编译器
- 数据结构
- C语言项目案例
- C++教程
- OpenCV
- Qt教程
- Unity 3D教程
- UE4
- STL
- Redis
- Android教程
- JavaScript
- PHP
- Mybatis
- Spring Cloud
- Maven
- vi命令
- Spring Boot
- Spring MVC
- Hibernate
- Linux
- Linux命令
- Shell脚本
- Java教程
- 设计模式
- Spring
- Servlet
- Struts2
- Java Swing
- JSP教程
- CSS教程
- TensorFlow
- 区块链
- Go语言教程
- Docker
- 编程笔记
- 资源下载
- 关于我们
- 汇编语言
- 大数据
- 云计算
- VIP视频