Go入门(3):打包和工具链

  • A+
所属分类:go语言 学习笔记

第三章学习笔记

 

在Go语言里,包是个非常重要的概念。其设计理念是使用包来封装不同语义单元的功能。这样做,能够更好地复用代码,并对每个包内的数据的使用有更好的控制。

一、定义包——如何把代码组织到包里

所有Go语言的程序都会组织成若干组文件,每组文件被称为一个包。这样每个包的代码都可以作为很小的复用单元,被其他项目引用。

所有的.go 文件,除了空行和注释,都应该在第一行声明自己所属的包。每个包都在一个单
独的目录里。不能把多个包放到同一个目录中,也不能把同一个包的文件分拆到多个不同目录中。
这意味着,同一个目录下的所有.go 文件必须声明同一个包名。

1.命名

给包命名的惯例是使用包所在目录的名字。

给包及其目录命名时,应该使用简洁、清晰且全小写的名字,这有利于开发时频繁输入包名。

记住,并不需要所有包的名字都与别的包不同,因为导入包时是使用全路径的,所以可以区分同名的不同包。一般情况下,包被导入后会使用你的包名作为默认的名字,不过这个导入后的名字可以修改。这个特性在需要导入不同目录的同名包时很有用。

2.main包

在Go语言里,命名为main的包具有特殊的含义。Go语言的编译程序会试图把这种名字的包编译为二进制可执行文件。所有用Go语言编译的可执行程序都必须有一个名叫main的包。

当编译器发现某个包的名字为main时,它一定也会发现名为main()的函数,否则不会创建可执行文件。main()函数是程序的入口。

二、导入包

1.import语句告诉编译器到磁盘的哪里去找想要导入的包。导入包需要使用关键字import,它会告诉编译器你想引用该位置的包内的代码。如果需要导入多个包,习惯上是将import语句包装在一个导入块中。编译器会使用Go环境变量设置的路径,通过引入的相对路径来查找磁盘上的包。

A.标准库中的包会在安装Go的位置找到。

B.Go开发者创建的包会在GOPATH环境变量指定的目录里查找。GOPATH指定的这些目录就是开发者的个人工作空间。
编译器会首先查找Go的安装目录,然后才会按顺序查找GOPATH变量里列出的目录.

2.远程导入

目前的大势所趋是,使用分布式版本控制系统(Distributed Version Control Systems,DVCS)来分享代码

import "github.com/spf13/viper"
如果路径包含URL,可以使用Go工具链从DVCS获取包,并把包的源代码保存在GOPATH指向的路径里与URL匹配的目录里。这个获取过程使用go get命令完成。go get将获取任意指定的URL的包,或者一个已经导入的包所依赖的其他包。由于go get的这种递归特性,这个命令会扫描某个包的源码树,获取能找到的所有依赖包。

3.导入的多个包具有相同的名字

重名的包可以通过命名导入来导入。命名导入是指,在import语句给出的包路径的左侧定义一个名字,将导入的包命名为新名字。

4.当你导入了一个不在代码里使用的包时,Go 编译器会编译失败,并输出一个错误。Go 开发
团队认为,这个特性可以防止导入了未被使用的包,避免代码变得臃肿

5.用户可能需要导入一个包,但是不需要引用这个包的标识符。在这种情况,可以使用空白标识符_来重命名这个导入。我们下节会讲到这个特性的用法。

三、函数 init

每个包可以包含任意多个 init 函数,这些函数都会在程序执行开始的时候被调用。所有被
编译器发现的 init 函数都会安排在 main 函数之前执行。init 函数用在设置包、初始化变量
或者其他要在程序运行前优先完成的引导工作。

数据库初始化等等

四、使用Go的工具——节约时间,提升效率

1.编译和执行
go bulid 编译
go clean ——删除编译生成的可执行文件
go run 执行

2.代码检查和格式化
go vet 检测代码的常见错误——每次对代码先执行go vet再将其签入源代码库是一个很好的习惯。
go fmt后面跟文件名或者包名,就可以调用这个代码格式化工具。fmt命令会自动格式化开发人员指定的源代码文件并保存。很多Go开发人员会配置他们的开发环境,在保存文件或者提交到代码库前执行go fmt。

五、文档

1.生成文档
A.在终端上直接使用go doc命令来打印文档
B.使用godoc程序来启动一个Web服务器,通过点击的方式来查看Go语言的包的文档

2.浏览文档
终端 godoc -http=:6060
http://localhost:6060可以看到一个页面,包含所有Go标准库和你的GOPATH下的Go源代码的文档
Go文档工具最棒的地方在于,它也支持开发人员自己写的代码。如果开发人员遵从一个简单的规则来写代码,这些代码就会自动包含在godoc生成的文档里。为了在godoc生成的文档里包含自己的代码文档,开发人员需要用下面的规则来写代码和注释。
用户需要在标识符之前,把自己想要的文档作为注释加入到代码中。这个规则对包、函数、类型和全局变量都适用。注释可以以双斜线开头,也可以用斜线和星号风格。

如果想给包写一段文字量比较大的文档,可以在工程里包含一个叫作 doc.go 的文件,使用同样的包名,并把包的介绍使用注释加在包名声明之前。

六、与其他Go开发者合作

1.以分享为目的创建代码库
包应该在代码库的根目录中(Go语言新手常犯的一个错误是,在公用代码库里创建一个名为code或者src的目录。如果这么做,会让导入公用库的语句变得很长。为了避免过长的语句,只需要把包的源文件放在公用代码库的根目录就好)

包可以非常小——不要在意包只支持几个API,或者只完成一项任务

对代码执行go fmt

给代码写文档

七、依赖管理

现在最流行的依赖管理工具是Keith Rarik写的godep、Daniel Theophanes写的vender和Gustavo Niemeyer开发的gopkg.in工具。gopkg.in能帮助开发人员发布自己的包的多个版本。

1.第三方依赖

像godep和vender这种社区工具已经使用第三方(verdoring)导入路径重写这种特性解决了依赖问题。其思想是把所有的依赖包复制到工程代码库中的目录里,然后使用工程内部的依赖包所在目录来重写所有的导入路径。
缺点:在依赖管理之后,导入路径需要重写成工程内部依赖包的路径。可以看到这些导入路径非常长,不易于使用
好处:引入依赖管理将所有构建时依赖的源代码都导入到一个单独的工程代码库里,可以更容易地重新构建工程。使用导入路径重写管理依赖包的另外一个好处是这个工程依旧支持通过go get获取代码库。当获取这个工程的代码库时,go get可以找到每个包,并将其保存到工程里正确的目录中。

2.对 gb 的介绍
gb是一个由Go社区成员开发的全新的构建工具。gb意识到,不一定要包装Go本身的工具,也可以使用其他方法来解决可重复构建的问题。

gb背后的原理源自理解到Go语言的import语句并没有提供可重复构建的能力。import语句可以驱动go get,但是import本身并没有包含足够的信息来决定到底要获取包的哪个修改的版本。go get无法定位待获取代码的问题,导致Go工具在解决重复构建时,不得不使用复杂且难看的方法。

gb的创建源于上述理解。gb既不包装Go工具链,也不使用GOPATH。gb基于工程将Go工具链工作空间的元信息做替换。这种依赖管理的方法不需要重写工程内代码的导入路径。而且导入路径依旧通过go get和GOPATH工作空间来管理。

一个gb工程就是磁盘上一个包含src/子目录的目录。符号$PROJECT导入了工程的根目录中,其下有一个src/的子目录中。这个符号只是一个简写,用来描述工程在磁盘上的位置。$PROJECT不是必须设置的环境变量。事实上,gb根本不需要设置任何环境变量。

gb 工程会区分开发人员写的代码和开发人员需要依赖的代码。开发人员的代码所依赖的代码被称作第三方代码(vendored code)。gb工程会明确区分开发人员的代码和第三方代码
工程中存放开发人员写的代码的位置 $PROJECT/src/
存放第三方代码的位置$PROJECT/vendor/src/

gb 一个最好的特点是,不需要重写导入路径。

gb工具首先会在$PROJECT/src/目录中查找代码,如果找不到,会在$PROJECT/vender/src/目录里查找。与工程相关的整个源代码都会在同一个代码库里。自己写的代码在工程目录的src/目录中,第三方依赖代码在工程目录的vender/src子目录中。这样,不需要配合重写导入路径也可以完成整个构建过程,同时可以把整个工程放到磁盘的任意位置。这些特点,让gb成为社区里解决可重复构建的流行工具。

注意:gb工程与Go官方工具链(包括go get)并不兼容。因为gb不需要设置GOPATH,而Go工具链无法理解gb工程的目录结构,所以无法用Go工具链构建、测试或者获取代码。构建(如代码清单3-16所示)和测试gb工程需要先进入$PROJECT目录,并使用gb工具。
构建gb工程 gb build all
很多Go工具支持的特性,gb都提供对应的特性。gb还提供了插件系统,可以让社区扩展支持的功能。其中一个插件叫作vender。这个插件可以方便地管理$PROJECT/vender/src/目录里的依赖关系。想了解更多gb的特性,可以访问这个网站:getgb.io。

八、总结

在Go语言中包是组织代码的基本单位。

环境变量GOPATH决定了Go源代码在磁盘上被保存、编译和安装的位置。

可以为每个工程设置不同的GOPATH,以保持源代码和依赖的隔离。

go工具是在命令行上工作的最好工具。

开发人员可以使用go get来获取别人的包并将其安装到自己的GOPATH指定的目录。

想要为别人创建包很简单,只要把源代码放到公用代码库,并遵守一些简单规则就可以了。

Go语言在设计时将分享代码作为语言的核心特性和驱动力。

推荐使用依赖管理工具来管理依赖。

有很多社区开发的依赖管理工具,如godep、vender和gb。

发表评论

您必须才能发表评论!