组织你的 Go 代码
安德鲁・格朗德
2012 年 8 月 16 日
介绍#
Go 代码的组织方式与其他语言不同。这篇文章讨论了如何命名和打包 Go 程序的元素以最好地为其用户服务。
选择好名字#
您选择的名称会影响您对代码的看法,因此在命名包及其导出的标识符时请多加注意。
包的名称为其内容提供了上下文。例如,标准库中的 bytes 包会导出 “Buffer
类型。 Buffer
的名称本身并不能很好地描述,但是当与包名结合使用时,其含义就很清楚了:bytes.Buffer
。如果包的描述性名称较少,如 util
,缓冲区可能会获得更长且更笨拙的 util.BytesBuffer
。
在工作时不要为重命名感到害羞。当您花时间在程序上时,您将更好地理解程序的各个部分如何组合在一起,因此,它们的名称应该是什么。无需将自己锁定在早期决策中。 (gofmt 命令具有一个 -r
标志,该标志提供了语法感知的搜索和替换,使大规模重构更加容易。)
良好的名称是软件界面中最重要的部分:名称是代码的每个客户端都会看到的第一件事。因此,精心选择的名称是好的文档的起点。以下许多做法都是源于良好的命名。
选择一个好的导入路径(使您的软件包 “可以获取”)#
导入路径是用户用来导入软件包的字符串。它指定软件包源代码所在的目录(相对于 $GOROOT/src/pkg
或 $GOPATH/src
)。
导入路径应该是全局唯一的,因此请使用源存储库的路径作为基础。例如,来自 go.net 子存储库的 websocket
软件包的导入路径为 “ golang.org/x/net/websocket”
。 Go 项目拥有路径 “ github.com/golang”
,因此该路径不能被其他作者用于其他软件包。由于存储库 URL 和导入路径是相同的,因此 go get
命令可以自动获取并安装软件包。
如果您不使用托管源存储库,请选择一些唯一的前缀,例如域,公司或项目名称。例如,所有 Google 内部 Go 代码的导入路径均以字符串 “ google”
开头。
导入路径的最后一个元素通常与包名称相同。例如,导入路径 "net/http"
包含程序包 http
。这不是必需的 - 您可以根据需要使它们有所不同 - 但出于可预测性的考虑,应遵循约定:用户可能会惊讶 import"foo / bar''
将标识符 quux
引入包名称空间。
有时人们将 GOPATH
设置为源存储库的根目录,并将其程序包放在相对于存储库根目录的目录中,例如 “"src / my / package"
。一方面,这使导入路径保持较短(“"my / package"
而不是 " github.com/me/project/my/package"
),但另一方面,它破坏了 go get
并迫使用户重新设置他们的 GOPATH
以使用该软件包。不要这样。
最小化导出的接口#
您的代码可能由许多有用的小代码组成,因此很容易在程序包的导出接口中公开很多功能。抵制这种冲动!
您提供的接口越大,您必须支持的越多。用户将很快依赖于导出的每种类型,函数,变量和常量,从而创建了一个隐含的合同,必须永久遵守该合同,否则有可能破坏用户程序。在准备 Go 1 时,我们仔细检查了标准库的导出接口,并删除了我们尚未准备提交的部分。分发自己的库时,应采取类似的措施。
如有疑问,请排除在外!
放入包中的物品#
将所有内容都放入 “抓包” 软件包很容易,但是这稀释了软件包名称的含义 (因为它必须包含很多功能),并迫使软件包的小部分用户进行大量的编译和链接不相关的代码。
另一方面,将代码分成小包也很容易过分,在这种情况下,您可能会陷入界面设计的泥潭,而不仅仅是完成工作。
请参阅 Go 标准库作为指南。它的某些程序包很大,而有些则很小。例如,http 包包含 17 个源文件 (不包括测试) 并导出 109 个标识符,而 [hash 包](https:///golang .org/pkg /hash/) 包含一个仅导出三个声明的文件。没有硬性规定。考虑到它们的上下文,两种方法都是合适的。
话虽如此,包主体通常比其他包大。复杂的命令包含许多在可执行程序上下文之外很少使用的代码,并且将所有内容都放在一个位置通常更简单。例如,go 工具跨越 34 个文件分布了 12000 多行。
记录您的代码#
好的文档是可用和可维护的代码的基本素质。阅读 Godoc:记录 Go 代码文章,了解如何编写好的 doc 注释。
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
推荐文章: