在前两个章节 Go 语言模块化编程 - go module ( 一 ) 和 Go 语言模块化编程 - go module ( 二 ) 中,我们简单的介绍了一下 go module
的基础知识和会用到的工具链,本章节我们可以开始我们的第一个 go module
之旅了
建立实验环境
我们将使用最近发布的 go1.11beta2 来开启我们的 go module 实验之旅
安装 Go 1.11 的方法有很多种,我们可以打开官方的下载页面 https://golang.org/dl/ 一直拉到最底部,点开 「 Unstable version 」 就可以看到下载连接
-
如果你从未安装过,可以选择一个适合你的平台的版本,然后点击链接下载安装
如果你不知道怎么安装,可以参考我们的 Golang 基础教程:Go 语言环境配置
-
如果你已经安装过,则可以通过下面的命令快速安装
go get golang.org/dl/go1.11beta2
注意:使用此方法安装的,因为
go1.11beta2
还不是正式稳定版,所有的命令都是go1.11beta2
开头而非go
安装完成后就可以使用 go version
或 go1.11beta2 version
命令查看下当前的版本
$ go version go version go1.11beta2 darwin/amd64
如果你感兴趣,可以使用 go help mod
命令查看下 go module 的手册
之前的开发模式 GOPATH mode
在 go module
出现之前,我们的开发一般是下面这种流程,假设我们当前的项目需要依赖 github/ijoywan/c
我们在 ~/go/a
目录下建立一个 hello
目录 ( 注意: $GOPATH = /Users/yufei/Developer/go
,显然 hello
目录并不在 GOPATH
下面)。 ~/go/a/hello/
目录下有一个 hello.go
文件,内容如下
~/go/a/hello/hello.go
package main /* * hello.go */ import "github.com/ijoywan/c" func main() { c.CallC() }
保存,然后使用 go build hello.go
构建下 hello.go
这个源码文件,会输出如下错误
$ go build hello.go hello.go:7:8: cannot find package "github.com/ijoywan/c" in any of: /usr/local/go/src/github.com/ijoywan/c (from $GOROOT) /Users/yufei/Developer/go/src/github.com/ijoywan/c (from $GOPATH)
构建错误!错误原因很明了:在本地的 GOPATH
下并没有找到 github.com/ijoywan/c
路径的 package c
。传统 fix 这个问题的方法是手工将 package c
通过 go get
下载到本地 (并且 go get 会自动下载package c
所依赖的 package d
)
$ go get github.com/ijoywan/c
完成后然后使用下面的命令就可以运行了
lie:hello luojianguo$ go get github.com/ijoywan/c lie:hello luojianguo$ go run hello.go call C: v1.0.0 --> call D: Hello World! FROM Module D: v5.2.0 --> call D end
这种我们最熟悉的 Go compiler 从 $GOPATH
下(以及 vendor
目录下)搜索目标程序的依赖包的模式称为:「 GOPATH mode 」
go module 开发模式 module-aware mode
Go module
的引入在 Go 1.8
版本上更进了一步,它引入了一种新的依赖模式 「 module-aware」
在该模式下,某源码树 ( 通常是一个 repo ) 的顶层目录下会放置一个 go.mod
文件,每个 go.mod
文件定义了一个 module
,而放置 go.mod
文件的目录被称为 module root
目录(通常对应一个 repo 的 root 目录,但不是必须的)
module root 目录以及其子目录下的所有 Go package 均归属于该 module,除了那些自身包含 go.mod
文件的子目录
在 「 module-aware 」模式下,go 编译器将不再在 GOPATH
下面以及 vendor
下面搜索目标程序依赖的第三方 Go packages
接下来我们改造下刚刚的项目,看一下在 「 module-aware 」 模式下的 hello.go
的构建过程
我们首先在 ~/go/a/hello/
目录下创建一个 go.mod
文件,并输入以下内容
~/go/a/hello/go.mod
module hello
接着使用下面的命令重新运行 hello.go
$ go run hello.go go: finding github.com/ijoywan/c latest go: finding github.com/ijoywan/d v1.0.0 go: downloading github.com/ijoywan/d v1.0.0 call C: v1.0.0 --> call D: Hello World! FROM Module D: v5.2.0 --> call D end
可以看到在这种模式下,go 编译器并没有去使用之前就已经下载好的 GOPATH
目录下的 github.com/ijoywan/c
和 github.com/ijoywan/d
。而是主动去下载这两个包并成功编译
接下来我们使用 cat go.mod
命令看看 go build
和 go run
命令执行后的 go.mod
文件的内容
module hello require github.com/ijoywan/c v0.0.0-20180803083505-aaafa13e3e67 // indirect
看到这个文件内容,你是否会疑问,为啥 github.com/ijoywan/d
没有包含进来
其实我也有疑问,但目前这个章节我还不想去追溯,因为这涉及到依赖和版本的问题
其实在改造的过程,我掉进了很多坑,尤其是版本号这个坑,如果你看我的 github.com
上的提交记录,就会知道这个坑有多大
本章节,我们就到此结束把,有关更多问题,我们会在接下来的章节中继续讲解