go modules
模块是相关Go包的集合。modules是源代码交换和版本控制的单元。 go命令直接支持使用modules,包括记录和解析对其他模块的依赖性。modules替换旧的基于GOPATH的方法来指定在给定构建中使用哪些源文件。
如何使用 Modules ?
GO111MODULE
GO111MODULE
GO111MODULEoffonauto(默认值)
GO111MODULE=offGO111MODULE=onGO111MODULE=auto
$GOPATH/pkg
go mod
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(解释为什么需要依赖) |
如何在项目中使用
示例一:创建一个新项目
GOPATH 目录之外go mod initgo.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文件一旦创建后,它的内容将会被go toolchain全面掌控。go toolchain会在各类命令执行时,比如go get、go build、go mod等修改和维护go.mod文件。
modulerequirereplaceexclude
modulerequirereplaceexclude
- 添加依赖
新建一个 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 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
复制代码
现在查看go.mod 内容:
$ 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
)
复制代码
go module 安装 package 的原則是先拉最新的 release tag,若无tag则拉最新的commit,详见 Modules官方介绍。 go 会自动生成一个 go.sum 文件来记录 dependency tree:
$ 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.gogo list -m -u allgo get -u need-upgrade-packagego 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文件也会更改
示例二:改造现有项目(helloword)
项目目录为:
$ tree
.
├── api
│ └── apis.go
└── server.go
1 directory, 2 files
复制代码
server.go 源码为:
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")
}
复制代码
go mod init ***
$ 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
复制代码
server.go
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
)
复制代码
那为什么会抛出这个错误呢?
变更引入方法
- 更新旧的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"))
}
复制代码
一个小坑go build github.com/valyala/fasttemplate: module requires go 1.12go mod
- 到这里就和新创建一个项目没什么区别了
使用replace替换无法直接获取的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
复制代码
参考链接
References
[1] Modules官方介绍: github.com/golang/go/w… [2] issue: github.com/golang/go/i… [3] 这种错误: github.com/golang/go/i… [4] Modules官方介绍: github.com/golang/go/w… [5] Golang 1.11 新功能介紹 – Modules: www.lightblue.asia/golang-1-11… [6] What are Go modules and how do I use them?: talks.godoc.org/github.com/… [7] go mod doesn't work for github.com/gomarkdown/markdown/html : github.com/golang/go/i… [8] 再探go modules:使用与细节: www.cnblogs.com/apocelipes/… [9] 初窥Go module: tonybai.com/2018/07/15/…