前言
想必大家都有一种感觉,作为Go开发者好像遇到的每一个项目都是特别不同的目录结构,先不说大体相似吧,基本都是风格不同,让初学者不好构建自己的项目目录规范结构。那么Go官方有标准的目录结构吗?答案是没有。当然初学者刚学习的时候一个main.go就解决了,但是项目一旦大起来就不得不考虑一个结构清晰,分层合理的文件夹结构,项目的目录结构通常也是门面,内行人通过目录结构基本就能看出开发者是否有经验,针对这个问题我们来看看Go项目目录应该怎么去命名。
Go生态标准目录
这是Go应用程序项目的基本布局。这不是核心Go开发团队定义的官方标准;然而,这是Go生态系统中一组常见的历史和新兴项目布局模式。其中一些图案比其他图案更受欢迎。它还具有一些小的增强功能,以及任何足够大的现实世界应用程序通用的几个支持目录。(这句话是从golang-standards/project-layout介绍中翻译过来的),它的结构如下:
├── api
├── assets
├── build
│ ├── ci
│ └── package
├── cmd
│ └── _your_app_
├── configs
├── deployments
├── docs
├── examples
├── githooks
├── init
├── internal
│ ├── app
│ │ └── _your_app_
│ └── pkg
│ └── _your_private_lib_
├── pkg
│ └── _your_public_lib_
├── scripts
├── test
├── third_party
├── tools
├── vendor
├── web
│ ├── app
│ ├── static
│ └── template
├── website
├── .gitignore
├── LICENSE.md
├── Makefile
├── README.md
└── go.mod
可见,这种项目目录布局适应绝大多数应用,当然想要更细致的区分可以看项目对目录更具体的拆分,我们只拿一些常见适合我们进行说明,对project-layout的目录总结如下图。
会用makefile吗
Make 是一个构建自动化工具,会在当前目录下寻找 Makefile 或 makefile 文件。如果存在,会依据 Makefile 的构建规则去完成构建,在windows环境下可以用GitBash来代替系统命令,或者安装make-4.2.1-without-guile-w32-bin.zip(地址:windows支持make命令),我们可以看看makefile的语法。
当然了,实际上 Makefile 内都是你根据 make 语法规则,自己编写的特定 Shell 命令等。它是一个工具,规则也很简单。在支持的范围内,编译 A, 依赖 B,再编译 C,完全没问题。
Makefile 由多条规则组成,每条规则都以一个 target(目标)开头,后跟一个 : 冒号,冒号后是这一个目标的 prerequisites(前置条件),紧接着新的一行,必须以一个 tab 作为开头,后面跟随 command(命令),也就是你希望这一个 target 所执行的构建命令。
[target] ... : [prerequisites] ...
<tab>[command]
...
...
- target:一个目标代表一条规则,可以是一个或多个文件名。也可以是某个操作的名字(标签),称为伪目标(phony)
- prerequisites:前置条件,这一项是可选参数。通常是多个文件名、伪目标。它的作用是 target 是否需要重新构建的标准,如果前置条件不存在或有过更新(文件的最后一次修改时间)则认为 target 需要重新构建
- command:构建这一个 target 的具体命令集
我们可以参考下Go的makefile怎么写,一个参考的demo(go-makefile-example) ,我们日常开发中基本不会写这么复杂的,大多数都是类似下面这种写一些简单的。
//Go项目中示例demo
BINARY_NAME=main.out
build:
go build -o ${BINARY_NAME} main.go
run:
go build -o ${BINARY_NAME} main.go
./${BINARY_NAME}
clean:
go clean
rm ${BINARY_NAME}
//运行
make build
make run
总结
公司内部定制也好,Go生态的规范目录也好。无论哪种目录结构都是为了让项目看起来一目了解,层次清楚,没有最好的只有合适团队开发的,但是在命名上尽量能和大众规范上保持一致,避免在语义上出现混淆。在解决分层、分模块之后彼此之间如何依赖和协作很多时候都是有拆分原则的,得多借鉴前人的经验。