文章目录
- 一、概述
- 二、结构化目录结构
- /build
- /build/ci
- /build/docker
- /build/package
- /cmd
- /doc
- /example
- /internal
- /internal/app
- /internal/pkg
- /pkg
- /vendor
- /test
- /tool
一、概述
需要规定每个目录下存放什么文件、实现什么功能,以及各个目录间的依赖关系是什么等。一个好的目录结构至少要满足以下几个要求:
- 命名清晰:名称要清晰、简洁,不要太长也不要太短,要能清晰地表达出该目录实现的功能,并且最好用单数。一方面是因为单数足以说明这个目录的功能,另一方面可以统一规范,避免单复混用的情况。
- 功能明确:它所要实现的功能应该是明确的、并且在整个项目目录中具有很高的辨识度。也就是说,当需要新增一个功能时,我们能够非常清楚地知道把这个功能放在哪个目录下。
- 全面性:目录结构应该尽可能全面地包含研发过程中需要的功能,例如文档、脚本、源码管理、API 实现、工具、第三方包、测试、编译产物等。
- 可预测性:项目规模一定是从小到大的,所以一个好的目录结构应该能够在项目变大时,仍然保持之前的目录结构。
- 可扩展性:每个目录下存放了同类的功能,在项目变大时,这些目录应该可以存放更多同类功能。
根据功能,可以将目录结构分为两种:
- 平铺式目录结构,主要用在Go包中,相对来说比较简单。
平铺方式就是在项目的根目录下存放项目的代码,整个目录结构看起来更像是一层的,这
种方式在很多框架/库中存在,使用这种方式的好处是引用路径长度明显减少。比如:github.com/marmotedu/log/pkg/options
可以缩短为github.com/marmotedu/log/options
。
例如,log包github.com/golang/glog
就是平铺式的,目录如下:
$ ls glog/
glog_file.go glog.go glog_test.go LICENSE README
- 结构化目录结构,主要用在Go应用中,相对来说比较复杂。
二、结构化目录结构
┌── build
│ ├── ci
│ ├── docker
│ │ ├── proc_1
│ │ └── proc_2
│ └── package
├── cmd
│ ├── proc_1
│ │ └── main.go
│ └── proc_2
│ └── main.go
├── doc
│ ├── devel
│ │ ├── en-US
│ │ └── zh-CN
│ ├── guide
│ │ ├── en-US
│ │ └── zh-CN
│ ├── image
│ └── README.md
├── example
├── internal
│ ├── app
│ │ ├── proc_1
│ │ │ ├── command
│ │ │ ├── config
│ │ │ ├── constants
│ │ │ ├── db
│ │ │ ├── model
│ │ │ └── service
│ │ └── proc_2
│ │ ├── command
│ │ ├── config
│ │ ├── constant
│ │ ├── db
│ │ ├── model
│ │ └── service
│ └── pkg
│ ├── log
│ └── util
│ └── util.go
├── pkg
├── vendor
├── test
├── tool
├── CHANGELOG
├── CONTRIBUTING.md
├── go.mod
├── go.sum
├── LICENSE
└── README.md
/build
这里存放安装包和持续集成相关的文件。这个目录下有 3 个大概率会使用到的目录,在设计目录结构时可以考虑进去。
/build/ci
存放CI(travis,circle,drone)的配置文件和脚本。
/build/docker
存放子项目各个组件的Dockerfile
文件。
/build/package
存放容器(Docker)、系统(deb, rpm, pkg)的包配置和脚本。
/cmd
一个项目可能有很多组件(如存在多个独立运行的程序),可以把它们的main函数所在的文件夹统一放在本目录下(根据组件和功能模块进一步创建子目录)。
/doc
存放相关文档。
/example
存放示例代码。
/internal
存放项目的私有代码和库代码。
/internal/app
存放每个组件自身的私有代码,这些代码不会共享给其他项目 在引入其它项目internal
下的包时,Go语言会在编译时报错。其内部根据组件和功能模块进一步创建子目录。
/internal/pkg
存放项目内可共享,项目外不共享的包。这些包提供了比较基础、通用的功能,例如工具、错误码、用户验证等功能。建议是,一开始将所有的共享代码存放在/internal/pkg
目录下,当该共享代码做好了对外开发的准备后,再转存到/pkg
目录。
/pkg
Go语言项目中非常常见的目录,几乎能够在所有知名的开源项目(非框架)中找到它的身影,例如Kubernetes、Prometheus、Moby、Knative 等。该目录中存放可以被外部应用使用的代码库,其他项目可以直接通过import
导入这里的代码。所以,在将代码库放入该目录时一定要慎重。
/vendor
项目依赖,可通过go mod vendor
创建。需要注意的是,如果是一个Go库,不要提交vendor依赖包。
/test
用于存放其他外部测试应用和测试数据。
/tool
存放这个项目的支持工具。