go从1.11版本之后,就有一个实验特性modules。它是官方支持的包管理,跟社区的dep等等是有许多不同的。
没有vendor目录
不同于dep这些社区的包管理,go modules是没有vendor目录的。
不需要设置gopath
之前安装好go第一件事就是设置gopath,然后所有代码都得放在这个路径下。这样做的目的主要是为了能够让go确定模块的导入路径。
1.11版本之后不需要了,下载好go之后就可以跟其他语言一样,在自己电脑喜欢放代码的目录,创建一个目录就可以了。
当然原先的gopath还是有用的,一是兼容,二是存在下载下来的包。
上面说了没有vendor目录了。那么下载下来的包,就是放在GOPATH\pkg\mod目录下了。
导入路径包含版本
为了导入路径唯一跟允许多版本包兼容,版本号是会加入到导入路径中的。
比如模块github.com/CODE7070/example_module为了兼容之前老的版本,v1默认是不带路径。如果是v2,那么包的路径实际上就为:github.com/CODE7070/example_module/v2。
啥是导入路径唯一
如果新包跟老包共用同一个路径,那么新包就得完全兼容老包的所有接口。如果有一点不兼容,请使用新的导入路径来表示。这个就是导入路径唯一。
多版本兼容
经历过一些大项目的人都知道,要想使用某个包的新版本,可能是新功能使用新版本,已有功能继续使用老版本。如果使用dep,或者其他语言比如composer基本很难实现。但在go modules中是完全可以的。
使用方便
基本上只需要自己初始化下包就可以。使用:
go mode init 模块名
之后的事就交给go命令去处理了。要引入一个包,在其他语言中可能需要手动引入,比如composer req xxx,在go中是在运行命令的时候自动发现并引入的。
比如你使用github.com/CODE7070/example_module模块,你只需要在代码中import,然后直接就可以调用了。然后当使用go run xxx的时候,依赖会自动加入到go.mod文件里。
啥是go.mod
go的依赖就是定义在这个文件的。
module gihub.com/CODE7070/hello
require (
github.com/CODE7070/example_module v0.0.0-20181205174043-395f5f29526f // indirect
github.com/CODE7070/example_module/v2 v2.0.0 // indirect
)
上面就是一个go.mod文件。在运行go mod init xxx的时候就会创建,当然也可以自己手动创建。
由于还是实验特性,因此这个文件的格式可能会发生变化。但是依照go的兼容,就算发生变化,也是会兼容这种格式的。
第一行module gihub.com/CODE7070/hello就是定义模块的名字。之后的require类似于import,主要是定义模块的依赖。
像版本号:v0.0.0-20181205174043-395f5f29526f是版本号-日期-提交的hash。通常这种格式都是非生产版本的。
第二行的v2.0.0一般就是可用于生产的版本了。
上面的文件意思就是一定一个模块hello,依赖example_module的v1某个提交版本跟v2正式版本。可以见到模块路径中有带了版本号example_module/v2。
实验
在非gopath路径下新建一个目录hello,然后使用:
go mod init gihub.com/CODE7070/hello
后面模块名请自己起。然后直接编写main.go文件:
package main
import "github.com/CODE7070/example_module"
func main() {
example_module.Hello()
}
编写好后用go执行:
go run main.go
可以看到成功输出hello world。并且go.mod中自动加入了依赖文件:
module gihub.com/CODE7070/hello
require (
github.com/CODE7070/example_module v1.0.0 // indirect
)
接着修改main.go,使用示例模块的版本2:
package main
import m1 "github.com/CODE7070/example_module"
import m2 "github.com/CODE7070/example_module/v2"
func main() {
m1.Hello()
m2.Hello()
}
然后继续使用go run main.go可以看到输出hello world跟hello world2了。说明两个版本共存成功,并且go.mod文件变为:
module gihub.com/CODE7070/hello
require (
github.com/CODE7070/example_module v1.0.0 // indirect
github.com/CODE7070/example_module/v2 v2.0.0 // indirect
)
可以发现没有vendor文件夹了。并且下载的依赖包被放在gopath/pkgmod路径下了。
环境变量
GO111MODULE这个环境变量就是用来控制go的module特性的,默认值为auto。
on:任何情况都开启
off:任何情况都关闭
auto:如果运行的命令在gopath路径下,就关闭。不是在gopath路径下就打开。
我们一般直接用默认值auto即可
我的公众号:编程说,欢迎关注:
有疑问加站长微信联系(非本文作者)