购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

5.2 Go语言典型项目结构

1. Go项目结构的最小标准布局

关于Go应用项目结构的标准布局是什么样子的,Go官方团队始终没有给出参考标准。不过作为Go语言项目的技术负责人,Russ Cox在一个开源项目的issue中给出了他关于Go项目结构的最小标准布局 的想法。他认为Go项目的最小标准布局应该是这样的:

// 在Go项目仓库根路径下

- go.mod
- LICENSE
- xx.go
- yy.go
...

- go.mod
- LICENSE
- package1
        - package1.go
- package2
        - package2.go
...

pkg、cmd、docs这些目录不应该成为Go项目标准结构的一部分,至少不是必需的。笔者认为Russ Cox给出的最小标准布局与Go一贯崇尚的“简单”哲学是一脉相承的,这个布局很灵活,可以满足各种Go项目的需求。

但是在Russ Cox阐述上述最小标准之前,Go社区其实是处于“无标准”状态的,早期Go语言自身项目的结构布局对现存的大量Go开源项目的影响依然存在,对于一些规模稍大些的Go应用项目,我们势必会在上述“最小标准布局”的基础上进行扩展。而这种扩展显然不会是盲目的,还是会参考Go语言项目自身的结构布局,于是就有了下面的 非官方标准的建议结构布局。

2. 以构建二进制可执行文件为目的的Go项目结构

基于Go语言项目自身的早期结构以及后续演进,Go社区在多年的Go语言实践积累后逐渐形成了一种典型项目结构,这种结构与Russ Cox的最小标准布局是兼容的,如图5-1所示。

052-1

图5-1 Go语言典型项目结构(以构建二进制可执行文件为目的的Go项目)

图5-1所示就是一个支持(在cmd下)构建二进制可执行文件的典型Go项目的结构,我们分别来看一下各个重要目录的用途。

Go 1.11引入的module是一组同属于一个版本管理单元的包的集合。Go支持在一个项目/仓库中存在多个module,但这种管理方式可能要比一定比例的代码重复引入更多的复杂性。因此,如果项目结构中存在版本管理的“分歧”,比如app1和app2的发布版本并不总是同步的,那么笔者建议将项目拆分为多个项目(仓库),每个项目单独作为一个module进行版本管理和演进。

3. 以只构建库为目的的Go项目结构

Go 1.4发布时,Go语言项目自身去掉了src下的pkg这一层目录,这个结构上的改变对那些以只构建库为目的的Go库类型项目结构有一定的影响。我们来看一个典型的Go语言库类型项目的结构布局,见图5-2。

054-1

图5-2 Go语言库项目结构

我们看到库类型项目结构与Go项目的最小标准布局也是兼容的,但比以构建二进制可执行文件为目的的Go项目要简单一些。

4. 关于internal目录

无论是上面哪种类型的Go项目,对于不想暴露给外部引用,仅限项目内部使用的包,在项目结构上可以通过Go 1.4版本中引入的internal包机制来实现。以库项目为例,最简单的方式就是在顶层加入一个internal目录,将不想暴露到外部的包都放在该目录下,比如下面项目结构中的ilib1、ilib2:

// 带internal的Go库项目结构

$tree -F ./chapter2/sources/GoLibProj
GoLibProj
├── LICENSE
├── Makefile
├── README.md
├── go.mod
├── internal/
│  ├── ilib1/
│  └── ilib2/
├── lib.go
├── lib1/
│  └── lib1.go
└── lib2/
      └── lib2.go

这样,根据Go internal机制的作用原理,internal目录下的ilib1、ilib2可以被以GoLibProj目录为根目录的其他目录下的代码(比如lib.go、lib1/lib1.go等)所导入和使用,但是却不可以为GoLibProj目录以外的代码所使用,从而实现选择性地暴露API包。当然internal也可以放在项目结构中的任一目录层级中,关键是项目结构设计人员明确哪些要暴露到外层代码,哪些仅用于同级目录或子目录中。

对于以构建二进制可执行文件类型为目的的项目,我们同样可以将不想暴露给外面的包聚合到项目顶层路径下的internal下,与暴露给外部的包的聚合目录pkg遥相呼应。

小结

以上两个针对构建二进制可执行文件类型以及库类型的项目参考结构是Go社区在多年实践后得到公认且使用较为广泛的项目结构,并且它们与Russ Cox提出的Go项目最小标准布局是兼容的,对于稍大型的Go项目来说很有参考价值。但它们并不是必需的,在Go语言早期,很多项目将所有源文件都放在位于项目根目录下的根包中,这个方法也适合一些小规模项目。

对于以构建二进制可执行文件类型为目的的项目来说,受Go 1.4项目结构影响,将pkg这一层次目录去掉也是很多项目选择的结构布局方式。

上述参考项目结构与产品设计开发领域的最小可行产品(Minimum Viable Product,MVP)的思路异曲同工,开发者可以在这样一个最小的项目结构核心的基础上根据实际需要进行扩展。 waiJi6sThwI2dPAoQm6bX0RmAzd26W5HQpg6AWYH7QJLR67wYZcL6f8Ua4XXnyjP

点击中间区域
呼出菜单
上一章
目录
下一章
×