在Go中,包是一个非常重要的概念,我们利用包来封装不同语义单元的功能,加强复用代码
首先是Go中的包,所有Go语言的程序都会组织为若干的文件,每组文件被称为一个包,每个包的代码都可以是一个复用单元,被其他的项目引用,比如http包,是如何利用包的特性组织功能的

这一目录包含了多个包,这些包分为了实现HTTP客户端和服务端 测试段 性能调节工具等小包
方便我们单独的导入和使用
所有的.go文件,除了空行和注释,都应该在第一行声明自己所属的包,每个包都在一个单独的目录中
对于包名的命名
我们一般是使用包所在目录的名字,我们可以清楚知道包名,对于net/http 在http目录下的所有文件都属于http
包名全小写
而且并不是要完全不同名,导入包的时候是使用全路径的,所以可以再导入后,对包名进行修改,显示别名
然后是main包
Go中,对于main包,是由特殊含义的
当编译的时候,发现了某个包的名字为main,同时要在包中发现名为main()的函数,不然编译出错,main函数式程序的入口,而且编译的时候,会使用main包所在目录的目录名作为可执行文件的文件名
比如我们创建一个hello.go的文件,在hello目录下
声明为main包,以及main函数

我们在hello目录下,执行命令 go build
如果是window端,会获得一个hello.exe 除此外都是hello文件,都可以进行相关的直接执行
然后是导入
我们看下如何将代码组织导入包中
import语句告诉编译器 到哪里去找包,
导入包需要关键字import和对应的代码块
导入的实例如下
import (
“fmt”
“io/ioutil”
“os”
“../words”
)
编译器会使用Go环境变量设置的路径,来查找并导入包
找到的顺序时有规律的
会现在安装位置找,然后是GoPath的指定目录,最后是个人工作空间
比如Go的安装目录为 /user/local/go
然后环境变量为
/home/myproject
这样查找包的顺序如下,我们以net/http包为例
我们查找顺序为
先去标准库,然后工作空间

一旦编译器满足了一个import语句的包,就会停止进一步的查找,会首先查找Go的安装目录
而且支持远程导入
比如从GitHub Launchpad 等地方导入
Go也是支持的,其本身会通过导入的路径来确定获取的代码是否在网络上
例如
import “github.com/spf13/viper”
go build会使用GOPATH的设置,在磁盘上搜索这个包,这个导入路径代表了一个URL,指向了GitHub上的代码库
或者通过go get命令完成,go get获取任意指定的URL的包
对于导入的包的别名命名
比如我们有多个convert,是从不同的地方导入的
我们可以通过命名导入来导入,命名导入可以让我们在import语句的的包的左侧重新定义一个名字
比如
“fmt”
myfmt “_mylib/fmt”
从而做到起别名
导入了一个不在代码的包的时候,会编译时失败
所以我们可以再导入的时候使用 空白标识符 _ 来重命名这个导入
函数init
对于之前包说的每个包含的多个init函数,这些函数会在程序执行开始之前被调用,init函数可以用于设置包,初始化变量,或者一些引导的工作
数据库驱动就会在启动的时候利用init函数将自身注册到sql包中
从而方便回调
利用下面的init
func init() {
d = new(PostgresDriver)
sql.Register(“postgres”, d)
}
如果我们导入了这个包,就会调用init函数,方便注入
然后展示一下使用空白标识符来导入包,这个新导入的包不需要使用,但是会被扫描到从而自动调用init函数
package main
import (
“database/sql”
_ “./postgres”
)
// main is the entry point for the application.
func main() {
sql.Open(“postgres”, “mydb”)
}
然后是工具链
我们看一下Go自带的命令行

通过输出的列表来看,其中包含了一个编译器,可以通过build命令启动
build和clean的命令分别执行编译和清理的工作
然后就是run命令
利用run命令,我们可以进行一次性的构建和执行
go run word.go
会先构建wordcount.go,然后执行构建后的程序
然后是Go的开发工具
go vet可以帮助我们检测代码的常见错误,
常见错误可以有
Printf类函数调用的时候,类型匹配错误的参数
定义常用的方法,方法签名的错误
错误的结构标签
指定字段名的结构字面量
然后是格式化代码
我们可以利用fmt命令,自动格式化开发人员指定的源代码文件并保存
常见的就是
![]()
执行go fmt后,得到

然后是go语言生成文档
生成文档的方式有两种
可以直接利用go doc的命令来打印文档,或者启动一个web服务器
通过点击来查看文档
命令行的获取当时很简单,加入我们需要用Go来开发读取Unix tar文件的程序,了解相关的tar文档
可以利用如下的命令
go doc tar
| package tar // import “archive/tar”
 Package tar implements access to tar archives. Tape archives (tar) are a file format for storing a sequence of files that can be read and written in a streaming manner. This package aims to cover most variations of the format, including those produced by GNU and BSD tar tools. const TypeReg = ‘0’ … var ErrHeader = errors.New(“archive/tar: invalid tar header”) … type Format int const FormatUnknown Format … type Header struct{ … } func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) type Reader struct{ … } func NewReader(r io.Reader) *Reader type Writer struct{ … } func NewWriter(w io.Writer) *Writer  | 
这样,方便我们直接翻看文档
对于web端的文档查看,可以使用如下的命令
godoc -http=[:port]
这样就在端口上启动了Web服务器
而且无论是web还是控制台,都是可以显示自己编写的代码文档
对于如何生成文档中
我们只需要遵守,将自己的文档作为注释放进到代码中就可以了
或者直接在工程中包含一个叫做doc.go的文件,使用相同的包名,并将包的介绍放在包名声明之前

其次是Go中的版本管理和依赖控制
在进行版本控制和依赖管理之前,首先说,如果我们想要做一些开源的包供他人使用,需要遵循一些特点
1.包要在代码库的根目录,这样,分享的时候,包的源代码就是代码库目录的结构的,对于导入时候语句变长,所以只需要将源文件放在公用代码库的根目录就可以了
2.包可以很小,可能只有几个API
3.对于编写完的,需要执行go fmt,提高自己代码的可读性
4.注意给代码编写文档
然后就是对其他第三方的依赖管理
因为Go本身不支持管理包的依赖,所以流行的依赖管理工具是godep和vender和gopkg,in工具
第三方的依赖
像是godep和vender这种社区工具,是使用的路径重写解决了路径依赖
将所有的依赖包复制到工程代码中,然后进行重写路径
比如godep
下面就是重写的路径
 
依赖的原代码放在了_workspace/src的目录中
如果需要import,则导入语句如下


这样将所有的依赖防在一个单独的工程代码库,更容易构建工程
然后是gb,可以是一个新的构建工具
gb不包装Go的工具链,不使用GOPATH,gb基于工程将GO工具链空间的元信息进行替换
这样就不修改了导入路径
我们尝试编写一个gb的工程
 
一个gb工程就是磁盘上一个包含 src 子目录,符号$PROJECT导入了工程的根目录中,其下有一个src/的目录,这个用来描述工程在磁盘上的位置
gb工程会区分开发人员写的代码和开发人员需要依赖的代码,开发人员的代码依赖的代码会称为第三方代码
工程中存放开发人员写的代码的位置
$PROJECT/src/
第三方代码的位置
$PROJECT/vendor/src
使用起来的也不需要重写导入路径,import基本如下

gb工具会在 $PROJECT/src/目录中查找,如果找不到就会在 $PROJECT/vender/src/目录中查找
这样,就不需要重写,就可以完成整个构建过程,这也是gb的流行原因
但是一旦使用了gb,可能和官方的工具链不兼容
对于测试和构建gb工程,都需要先进入 $PROJECT目录,然后使用gb工具
gb build all
这样,就可以进行构建和测试了
GO语言中包是组织代码的基本代码
环境变量GOPATH决定了Go源代码在磁盘上保存,编译的位置
每个工程可以设置不同的GOPATH
开发人员可以使用go get来获取别的包,并安装在自己的GOPATH
推荐使用依赖管理工具来管理依赖
诸如 godep vender gb