本文转载自微信公众号「脑子进煎鱼了」,作者陈煎鱼。转载本文请联系脑子进煎鱼了公众号。
大家好,我是煎鱼。
前段时间 Go 语言社区有一件事情引爆了热议,那就是 golang-standards/project8 : h v-layout 项目的 “Go 项目的标准布局” 之争。
没想到,五一假期,认真一看,这个D H H X issues 已经提出将近一个月了,仍然在热议阶段,我想,咱们需要好好的聊聊这个话题。
煎鱼带你了解下的前因后果,再分) . 8 Y * B享我的看法和业务真实情况。
背景
问题发生地
在 GitHub 上有一个项目 Spaghetti(github.com/adonovan/spaghetti),是 Go 软件包的一个x c G P ? 1 3依赖性分析工具。
该项目的目录结构如下:
看上去并不复杂,代码量不多,文件平铺也不超过一屏,就是一个布局比较简单的项目。
有一位老哥提出了一个 PR,明确的期望该项目按照 golang-stay % |nd; 9 J e nards/proj) { 1 8 + s @ect-layout 项* _ y Q & % R | &目给出$ Q : e N V的 “标准” 布局来调整。:
我猜测该项目} k * @ D h #可能是因为把 Go、HTML、JS、PNG 和 go.mod 文件等摆在了一起,引起了该同学的一丝丝纠结,觉得比较乱?
“标准布局“ 长什么样子
在 golang-stao o r H Ondards/project-layout 项目中,其自称:
项目的组织名也是 “golang-s/ e $ o Y T 9 H :tandards”,其提供了一个基本的 Go 项目布局,精简展示如下:
- project-layout
- ├──api
- ├──cmd
- ├──configs
- ├──docs
- ├──go.mod
- ├──init
- ├──internal
- ├──pkg
- ├──scripts
- ├──vendor
- ├──...
- /cmd:项目主要的应用程序。
- /internal:私有的应用程序代码库,这些是不希望被其他人导入的代码。
- 应用程序实际的代码可以放在 /iy ; 4nternal/app 目录(如:internal/app/myapp)。
- 应用程序的共享\ 9 T j | # 7 O代码放在 /internal/pkgC p @ h 8 Z = D + 目M P U , F J r k Y录(如:internal/pkg/myprivlib)中。
- /pkg:外部应用程序可以使用的库代码(如:/pkg/U x U + I Xmypubliclib)。其他项目将会导入这些库来保证项目可以正常运行。
- /vendor:应用程序的依赖关系,可通过执行 go mod venZ a j L U F V 4dor 执行得到。
- /configs:配置文件模板或默认配置。
- /init:系统初始化(systemd、up– \ ` 4 l . Hstart、sysv)和进程管理(runit、supervisord)配置。
- /scr/ { Q A ~ ] G \ [ipts::用于执行各种构建R b X ! @ J,安装7 # ;,分析等操作的脚本。
更具体的布局介绍,大家可以\ o 4 T O r ; a参见 project-lay9 ? T u 8 R B B tout 项目的 README,其基本把方方面面的目录都考虑到了(人多力量大)。
由于内容过于长,因此就不一一展示了。
Russ Cox 现身原因
不过很x c V c ^ 6 e _ \巧,该项目的作者是前 Google 员工9 6 [ 5,是 gopl.io 项目(5.1k stars)的作者。
在仅仅过去 23 分钟后,作为 GB ! F ToTeam Leader 的 RJ e x ; F ` auss Cox(@rsc)就现身,并提出新的 issue 表达出了反对意见:
在 golang-standa2 o X o 0 , H Brds/project-layout 项目的 Re a _ C t \ NEADME 中有明确指出这不是官方的标准,有如下声称:
it is a set ob c 1 Gf common historical and emerging proF o } 7ject layout patterns in the Go ecosystem.J S – z a 4 s i b
Russ Cox 主Z d b I要是对声称 “这是一套 Go 生态系统中常见的历史和新兴的项目布局模式” 这一说法表示了 “不准确y d } C M R V”T p C 3 c ^ 的意见。
例如:Go 生态系统中的绝大多数包都不会将可导入的包放在 pkg 子目录中。更广泛地说,这里描述的只是非常复杂的工程项目,而 Go 的仓库往往要简单得多。
另外,不幸的是,这套项a d [ 8 H目布局在组织名字上k – O H Q被称作 “golang-standards”(Golang 标准) 提出来,实际上并非真的是官方标准,有误导的情况存在。
Russ Cox 反对原因
在了解 project-layout 项目所提供的 “标准G y i“ 项目布局和 Russ Cox 提出 issues 的背景后。
我们进一步了解 Russ Cox 认为这不对的根本考I E $ @ X f U &虑。project-layout 这个项目有G 7 E _两个问题:
- 它声称是 Go 标准(Go standards)的主办方,但实际上并非} C i %如此,因为这些标准绝非 Go 官方标准。
- 它提出的项目\ @ (布m 3 y a H Z局标准过于复杂,不是一个合理的标准。
Go 项目布局的标准是什么
提出这个 issues 后,出现了一大堆人追问 Russ Cox,F ) W W到底何为 Go 项目的布局标准?
Russ Cox 给出了正式回应,一个可导入的 Go repo 的最小标准布局是:
- 在你的根目录下放一个 LI~ b U Y k OCENSE 文件。
- 在你的根目录下放一个 goc f + e O t.mod 文件。
- 将 Go~ z ~ 代码放在 repr 8 \ ? N & P 9 lo 中,放在根目录中,或者按照你认为合适的方式组织成一个目录树e = o | : a x。
就这样了,这就是 “标准”,没有g A =那么复杂。不需要像 project-layout 项目一样的布局。像是 Go 官方的 golang.org/x 仓库打破了 project-layout 所说的这些 “规则 “中的每一条。
Go 提案
在经历了长时间的口水战后,已经有人在 Go 官方仓库提出希望释出相关的提p + n + T w案(proposal):
猜测可能会有如下几种可能:
- GitHub 项目 golang-standards/prot b e + z L x Aject^ * ? q ; 0 ^ (-layout 愿意m y ~ t H 8 9 – Y更名,不再自称 ”golang-standards“,不过可K 1 E y q能性比较| Y : z %低,因为已经已多人提出,但作者没什么表示。
- Go 官方正式提供 Go 标准项目布局的说明。
- Go 官方不做约束,仅做表态,可能输出文章。
后续大家继续关注该提案,就可以知道发展了,传送门:issues #45861。
按照惯例,我猜测第三种可能性最I – O D :大,因为很难有人可以提供所有开发者认可的标准,每个事业部、团队的喜好& R 7 D都可能有所不同。
总结
实际上,任何东西自称 “XX 标准”,在名气大后,都会带来一些问题。m } g _ q F S d ?就像本文提到的 golang-sta4 % ~ wndards/project-layout 项目一样。
换位思考一下,若你是某个项目的 Leader,某一天你的同事,被人拿/ = 9 V 7着 “标准” 来建议修改时,说这是@ ` f \ y C =这个项u v m 7目的 “标准”,会不会很奇妙?
无独有偶,我有一个朋友,他们公司早年只有一套 DDD 标准,本想统一。结果后面每一\ ) T Z个介入 DDD 的业务同学,都认Y l h 5 7 Q : t 4为前人不标准,每个人都自创了一套 DD} ] g 6 p hD 标准。
总是会有小伙伴想让定义绝对的 “标准”,又或是 “最佳实践”。其实是难以定义的,最好的就是能够一个团队内形成基本共识,这里面牵扯到的不单单只有技术…