一个好的目录结构至少要满足以下几个要求。
- 命名清晰:目录命名要清晰、简洁,不要太长,也不要太短,目录名要能清晰地表达出该目录实现的功能,并且目录名最好用单数。一方面是因为单数足以说明这个目录的功能,另一方面可以统一规范,避免单复混用的情况。
- 功能明确:一个目录所要实现的功能应该是明确的、并且在整个项目目录中具有很高的辨识度。也就是说,当需要新增一个功能时,我们能够非常清楚地知道把这个功能放在哪个目录下。
- 全面性:目录结构应该尽可能全面地包含研发过程中需要的功能,例如文档、脚本、源码管理、API 实现、工具、第三方包、测试、编译产物等。
- 可预测性:项目规模一定是从小到大的,所以一个好的目录结构应该能够在项目变大时,仍然保持之前的目录结构。
- 可扩展性:每个目录下存放了同类的功能,在项目变大时,这些目录应该可以存放更多同类功能。
根据功能,我们可以将目录结构分为结构化目录结构和平铺式目录结构两种。
GoGo
2. 平铺式目录结构
Go
loggithub.com/golang/glog
$ ls glog/
glog_file.go glog.go glog_test.go LICENSE README
3. 结构化目录结构
GoGo
├── api
├── assets
├── build
├── cmd
├── configs
├── deployments
├── docs
├── examples
├── githooks
├── go.mod
├── init
├── internal
├── LICENSE.md
├── Makefile
├── pkg
├── README_zh-CN.md
├── scripts
├── test
├── third_party
├── tools
├── vendor
├── web
└── website
GoGoGo
3.1 Go 应用开发目录
开发的代码包含前端代码和后端代码,可以分别存放在前端目录和后端目录中。
3.1.1 /web
前端代码存放目录,主要用来存放 Web 静态资源,服务端模板和单页应用(SPAs)。
3.1.2 /cmd
main/cmd
$ ls cmd/
gendocs geniamdocs genman genyaml apiserver iamctl iam-pump
$ ls cmd/apiserver/
apiserver.go
/cmd/<组件名>/pkg/internal
3.1.3 /internal
/internal
internalGo
An import of a path containing the element “internal” is disallowed
if the importing code is outside the tree rooted at the parent of the
"internal" directory.
internalinternalinternal
$ ls internal/
apiserver authzserver iamctl pkg pump watcher
/internal
/internal/apiserver/internal/pkg/internal/pkg
/internal/pkg/pkg
3.1.4 /pkg
import
3.1.5 /vendor
go mod vendorGovendor
3.1.6 /third_party
forkgo/third_party/forkedforkupstream
3.2 Go 应用测试目录
3.2.1 /test
/testGo/test/data/test/testdata
._
3.3 Go 应用部署目录
3.3.1 /configs
confdconsul-template
apiVersion: v1
user:
username: ${CONFIG_USER_USERNAME} # iam 用户名
password: ${CONFIG_USER_PASSWORD} # iam 密码
3.3.2 /deployments
IaasPaaSKubernetesdeploy
3.3.3 /init
systemdupstartsysvrunitsupervisordsysemdunit
3.4 Go 应用项目管理目录
3.4.1 /Makefile
GoMakefileMakefile
lintgolangci-linttestgo test ./...buildCPUimage/image.pushDocker/Kubernetescleangenprotobuf pb.godeployreleaseDocker HubgithubhelpMakefileadd-copyrightswaggerswaggerAPIMakefile
makeformat -> lint -> test -> buildgen -> format -> lint -> test -> build
3.4.2 /scripts
该目录主要用来存放脚本文件,实现构建、安装、分析等不同功能。不同项目,里面可能存放不同的文件,但通常可以考虑包含以下 3 个目录:
/scripts/make-rulesmakefile/MakefileMakefile/scripts/make-rules/scripts/libshellshellshellshell/scripts/liblogging.shutil.sh/scripts/install/scripts
shelliam::log::info
3.4.3 /build
这里存放安装包和持续集成相关的文件。这个目录下有 3 个大概率会使用到的目录,在设计目录结构时可以考虑进去。
/build/packageDockerdebrpmpkg/build/ciCI/build/dockerDockerfile
3.4.4 /tools
/pkg/internal
3.4.5 /githooks
Gitcommit-msg
3.4.6 /assets
CSSJavaScript
3.4.7 /website
Github
3.5 Go 应用文档目录
3.5.1 /README.md
README
3.5.2 /docs
godoc
/docs/devel/{en-US,zh-CN}/docs/guide/{en-US,zh-CN}/docs/images
3.5.3 /CONTRIBUTING.md
CONTRIBUTING.md
3.5.4 /api
/apiAPI/api/protobuf-spec/api/thrift-spec/api/http-specopenapiswaggerAPI
3.5.5 /LICENSE
Apache 2.0MITBSDGPLMozillaLGPL
3.5.6 /CHANGELOG
CHANGELOG
3.5.7 /examples
存放应用程序或者公共包的示例代码
4. 不建议的目录4.1 /src
其中一个重要的原因是:在默认情况下,Go 语言的项目都会被放置到$GOPATH/src 目录下。这个目录中存放着所有代码,如果我们在自己的项目中使用/src 目录,这个包的导入路径中就会出现两个 src,例如:
$GOPATH/src/github.com/marmotedu/project/src/main.go
这样的目录结构看起来非常怪。
4.2 /xxs
Go
5. 建议
cmdpkginternal
$ tree --noreport -L 2 tms
tms
├── cmd
├── internal
├── pkg
└── README.md
GitGit.keep
$ ls -A build/ci/
.keep
先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦