
到目前位置我们一直在编写单文件代码,只有一个 main.go 文件。本节我们要开始朝完整的项目结构迈进,需要使用 Go 语言的模块管理功能来组织很多的代码文件。
细数 Go 语言的历史发展,模块管理经历了三个重要的阶段。第一阶段是通过全局的 GOPATH 来管理所有的第三方包,第二阶段是通过 Vendor 机制将项目的依赖包局部化,第三阶段是 Go 语言的最新功能 Go Module。
本节我们重点讲解前两个阶段,这两个阶段要求我们编写代码时必须在 GOPATH 下面对应的包路径目录里写。第三个阶段 Go Module 内容较新,也比较复杂需要另起一节单独讲解。
系统包路径
Go 语言有很多内置包,内置包的使用需要用户手工 import 进来。Go 语言的内置包都是已经编译好的「包对象」,使用时编译器不需要进行二次编译。可以使用下面的命令查看这些已经编译好的包对象在哪里。
// go sdk 安装路径
$ go env GOROOT
/usr/local/go
$ go env GOOS
darwin
$ go env GOARCH
amd64
$ ls /usr/local/go/darwin_amd64
total 22264
drwxr-xr-x 4 root wheel 136 11 3 05:11 archive
-rw-r--r-- 1 root wheel 169564 11 3 05:06 bufio.a
-rw-r--r-- 1 root wheel 177058 11 3 05:06 bytes.a
drwxr-xr-x 7 root wheel 238 11 3 05:11 compress
drwxr-xr-x 5 root wheel 170 11 3 05:11 container
-rw-r--r-- 1 root wheel 93000 11 3 05:06 context.a
drwxr-xr-x 21 root wheel 714 11 3 05:11 crypto
-rw-r--r-- 1 root wheel 24002 11 3 05:02 crypto.a
...
该命令显示出来的后缀名为 .a 的文件就是已经编译好的包对象。
全局管理 GOPATH
Go 语言的 GOPATH 路径下存放了全局的第三方依赖包,当我们在代码里面 import 某个第三方包时,编译器都会到 GOPATH 路径下面来寻找。GOPATH 目录可以指定多个位置,不过用户一般很少这样做。如果你没有人工指定 GOPATH 环境变量,编译器会默认将 GOPATH 指向的路径设定为 ~/go 目录。用户可以使用下面的命令看看自己的 GOPATH 指向哪里
$ go env GOPATH
/Users/qianwp/go
GOPATH 下有三个重要的子目录,分别是 src、pkg 和 bin 目录。src 目录存放第三方包的源代码,pkg 目录存放编译好的第三方包对象,bin 存放第三方包提供的二进制可执行文件。

当我们导入第三方包时,编译器优先寻找已经编译好的包对象,如果没有包对象,就会去源码目录寻找相应的源码来编译。使用包对象的编译速度会明显快于使用源码。
友好的包路径
Go 语言允许包路径带有网站域名,这样它就可以使用 go get 指令直接去相应的网站上拉去包代码。最常用的要数 http://github.com、http://gopkg.in、http://golang.org 这三个网址。
import "github.com/go-redis/redis"
import "golang.org/x/net"
import "gopkg.in/mgo.v2"
import "myhost.com/user/repo" // 个人提供的仓库
Go 语言不存在官方维护的集中包仓库,它将包的选择分散到开源社区网站。使用量最大的要数 http://github.com,我们平时使用的大部分第三方包都是来源于此。也可以使用自己公司提供的代码仓库,路径名用上公司代码仓库的域名即可。默认会使用 https 协议下载代码仓库 ,可以使用 -insecure 参数切换到 http 协议。
模块的标准结构
了解模块结构的最好办法就是看看别人的模块是怎么写的,这里我们来观察一下 mongo 包。使用下面的命令将 redis 的包下载本 GOPATH 目录下
$ go get gopkg.in/mgo.v2
进入到 GOPATH 目录下面的 src 子目录寻找刚刚下载的 mongo