go modules
是 golang 1.11 新加的特性。如今1.12 已经发布了,是时候用起来了。Modules官方定义为:html
模块是相关Go包的集合。modules是源代码交换和版本控制的单元。 go命令直接支持使用modules,包括记录和解析对其余模块的依赖性。modules替换旧的基于GOPATH的方法来指定在给定构建中使用哪些源文件。
GO111MODULE
GO111MODULEgit
GO111MODULE
有三个值:off
, on
和auto(默认值)
。github
GO111MODULE=off
,go命令行将不会支持module功能,寻找依赖包的方式将会沿用旧版本那种经过vendor目录或者GOPATH模式来查找。GO111MODULE=on
,go命令行会使用modules,而一点也不会去GOPATH目录下查找。GO111MODULE=auto
,默认值,go命令行将会根据当前目录来决定是否启用module功能。这种状况下能够分为两种情形:golang
当modules 功能启用时,依赖包的存放位置变动为
$GOPATH/pkg
,容许同一个package多个版本并存,且多个项目能够共享缓存的 module。
golang 提供了 go mod
命令来管理包。web
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 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文件一旦建立后,它的内容将会被go toolchain全面掌控。go toolchain会在各种命令执行时,好比go get、go build、go mod等修改和维护go.mod文件。
go.mod 提供了module
, require
、replace
和exclude
四个命令设计模式
module
语句指定包的名字(路径)require
语句指定的依赖项模块replace
语句能够替换依赖项模块exclude
语句能够忽略依赖项模块新建一个 server.go 文件,写入如下代码:api
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
如今查看go.mod 内容:bash
$ 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.go
发现跳过了检查并安装依赖的步骤。可使用命令 go list -m -u all
来检查能够升级的package,使用go get -u need-upgrade-package
升级后会将新的依赖版本更新到go.mod
go get -u
升级全部依赖项目目录为:
$ 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$ 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 )
这是由于 server.go 中使用 internal package 的方法跟之前已经不一样了,因为 go.mod会扫描同工做目录下全部 package 而且变动引入方法
,必须将 helloworld当成路径的前缀,也就是须要写成 import helloworld/api,以往 GOPATH/dep 模式容许的 import ./api 已经失效,详情能够查看这个 issue。
因此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")) }
一个小坑
:开始在golang1.11 下使用go mod 遇到过go build github.com/valyala/fasttemplate: module requires go 1.12
这种错误,遇到相似这种须要升级到1.12 的问题,直接升级golang1.12 就行了。幸好是在1.12 发布后才尝试的go mod
🤷♂️
因为某些已知的缘由,并非全部的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
[1] Modules官方介绍: https://github.com/golang/go/...
[2] issue: https://github.com/golang/go/...
[3] 这种错误: https://github.com/golang/go/...
[4] Modules官方介绍: https://github.com/golang/go/...
[5] Golang 1.11 新功能介紹 – Modules: https://www.lightblue.asia/go...
[6] What are Go modules and how do I use them?: https://talks.godoc.org/githu...
[7] go mod doesn't work for github.com/gomarkdown/markdown/html : https://github.com/golang/go/...
[8] 再探go modules:使用与细节: https://www.cnblogs.com/apoce...
[9] 初窥Go module: https://tonybai.com/2018/07/1...
最后,感谢女友支持和包容,比❤️
也能够在公号输入如下关键字获取历史文章:公号&小程序
| 设计模式
| 并发&协程