标准目录结构
背景
在编程项目中,项目结构的清晰性是非常重要的。一个好的项目结构可以使开发者更容易理解代码的组织方式,更快地找到需要的代码,更有效地进行代码的维护和扩展。然而,对于许多Go语言的项目来说,项目结构的问题是一个常见的痛点。
Go语言的项目结构并没有一个统一的标准,这使得不同的项目可能会有完全不同的结构。这种情况下,当开发者需要阅读或者维护别人的代码时,可能会花费大量的时间去理解项目的结构和代码的组织方式。此外,如果项目结构不清晰,可能会导致代码的重复,增加代码的复杂性,降低代码的可读性和可维护性。
因此,解决Go项目结构不明确的问题,可以帮助开发者提高编程效率,提高代码的质量,降低代码维护的难度。这需要我们对Go语言的项目结构进行深入的研究,找出最佳的项目结构,然后将这种结构推广到更多的Go语言项目中。
/myproject
├── /cmd
| ├── /app
| | └── main.go
| └── /anotherapp
| └── main.go
|
├── /pkg
| ├── mypackage1
| | ├── file1.go
| | └── file2.go
| └── mypackage2
| ├── file1.go
| └── file2.go
|
├── /internal
| ├── myinternalpackage
| | ├── file1.go
| | └── file2.go
|
├── /api
| └── api_definitions.proto
|
├── /web
| ├── static
| ├── templates
| └── main.go
|
├── /scripts
├── /configs
├── /build
├── /deployments
├── /test
├── go.mod
└── go.sum
目录结构解析
- /cmd: 包含主要的应用程序代码。每个应用程序都应该在这个目录下有一个独立的子目录,例如
/cmd/app、/cmd/anotherapp。每个子目录下通常包含一个 main.go 文件,用于启动应用程序。 - /pkg: 包含库代码,可以被其他项目引用。这些库应该是可复用的,独立于具体的应用程序。
- /internal: 类似于 /pkg,但是这里的代码仅对当前项目可见,不允许其他项目导入。这样可以确保内部实现的封装性。
- /api: 包含 API 定义,例如 Protocol Buffers 文件。
- /web: 包含与 Web 相关的代码,例如静态文件、模板以及 Web 应用程序的主要代码。
- /scripts: 包含运行脚本和工具的地方。
- /configs: 包含配置文件,用于应用程序的配置。 /build: 包含构建脚本和产生的可执行文件。
- /deployments: 包含部署脚本和配置文件。
- /test: 包含测试代码。
- go.mod 和 go.sum: Go Modules 的配置文件,用于管理项目的依赖关系。
核心目录
- cmd:应用启动入口文件夹,可以有多个应用,每个应用都有自己独立的文件夹和main.go启动文件
- pkg: 每个应用程序的具体实现入口,文件夹结构与cmd中应用文件夹结构一致,功能作用类似于java的controller层, 存放应用的的入口文件、加载配置文件、中间件函数等
- internal:每个应用程序的业务逻辑,文件夹结构与pkg一致,包括service层、model(orm映射)、repository(数据库操作,类似java的DAO层)以及其他工具文件
- configs:存放应用的配置文件
项目分层
各层文件如何组织
cmd:应用子目录以及对应的main启动文件。其中main启动文件主要用于
- 命令行参数解析
- 配置文件初始化入口
- 创建应用
- 加载路由
- service层结构体初始化
- 启动应用
pkg: 各个应用的入口目录
- app.go:用于创建并暴漏一个应用结构体并提供创建应用、启动应用和停止应用的方法
- a. 初始化数据库连接并返回*grom.DB
- b.通过model创建数据表
- app目录:设置路由和各个路由的处理函数
- a. router.api:对应与api接口的路由设置
- i.设置中间件
- ii.设置路由组
- iii.配置路由和handlefunction的处理关系
- b. middleware:存放中间件
- i.一个中间件一个文件,都共有一个包
- c. api目录:handlefunction的入口目录
- i. handler.go:响应体的封装
- ii. 每个模块的接口是一个文件夹,模块中每个接口放在独立的文件中,公用一个包
- 文件名按rest风格命名
- 使用到的数据流转结构体放到同一个的与模块名相同的文件中
- a. router.api:对应与api接口的路由设置
internal: 应用的Service层和DAO层
- model:用于设置数据表模型
- repository: 用于存放数据表操作结构和和方法
- a.每个模块存放在一个文件夹中
- b.文件已repo结尾
- c.文件中配置操作当前模块的结构体对象,主要用于执行sql,属性为*grom.DB。以及一个初始化该结构体的函数
- d.关联该结构体的业务处理方法
- xxxx_serice.go: 某个模块的业务处理文件
- a.定义一个结构体,属性是对应的repo数据库操作模块
- b.暴露一个初始化结构体的函数
- c.关联该结构体的业务处理方法
- service.go:统一管理各个模块的service结构体,用于pkg模块调用
- a.定义一个结构体,属性是所有的service结构体
- b.暴露一个初始化当前结构体的函数