本文首发地址:jianghushinian.cn/2023/02/25/…

Go 言语作为一门高效、简练、并发安全的言语,越来越受到开发者们的喜爱,特别是在 Web 开发及云原生范畴。而关于一个大型的 Go Web 项目而言,一个优异的目录结构规划是必不可少的。它可以协助咱们更好地安排代码、削减冗余、进步可保护性和可扩展性。在本文中,咱们将评论怎么规划一个优异的 Go Web 项目目录结构。

基本准则

在开始规划项目目录结构之前,咱们需求先了解一些规划目录的基本准则:

  • 可读性和可保护性:规划目录结构应该易于阅览和保护,目录称号要简练、明晰,最好能达到望文生义的效果。

  • 可扩展性和模块化:规划目录结构应该易于扩展和模块化,随着时间的推移,项目会不断变大,项意图目录结构应该可以很容易支撑这种变化。

  • 标准性和共同性:规划目录结构应该遵循标准和共同性,如无特殊情况,目录称号最好共同运用奇数方法(特殊情况可以打破,如 /docs/examples)。

Go 项目标准布局

前期的 Go 项目目录结构规划形形色色,由于大多数 Go 开发者都有其他编程言语根底,比方 Java、Python 等,这些开发者在规划 Go 项目时,目录结构往往会携带一些其他编程言语、框架所惯用的风格。

但许多情况下,直接套用其他编程言语风格的目录所规划出来的 Go 项目都会有许多不合理之处,为了改变现状,慢慢的 Go 言语社区诞生了许多更契合 Go 哲学的项目目录风格。而这其间,最著名的项目当属 golang-standards/project-layout。

golang-standards/project-layout 是一个 Go 社区保护的 Go 项目目录结构标准,它的目标是供给一种共同性的、易于了解和运用的目录结构,从而协助开发者更好地安排和办理自己的代码。

该项意图目录结构基于功能和约定进行安排,经过供给一种标准化的目录结构,可以使得不同的项目之间具有共同的代码安排方法,便于开发者了解和运用。

该项意图目录结构包括以下几个部分:

Go 应用程序相关目录

/cmd

这个目录首要担任程序的发动、初始化、中止等功能,故首要包括项意图入口文件 main.go,假如一个项目有多个组件,则可以寄存多个组件的 main.go,例如:

cmd
├── ctl
│ └── main.go
├── server
│ └── main.go
└── task
    └── main.go

不要在这个目录中放太多的代码,更不要放事务逻辑代码,保持整齐。

/internal

寄存项意图内部私有代码和库,不允许在项目外部运用。同时这也是 Go 在编译时强制履行的校验规矩,假如在其他项目中导入 internal 目录下的内容,Go(1.19) 在编译时会得到如下错误:

use of internal package xxx not allowed

注:xxx 为包括 internal 的包途径

在项意图目录树中的恣意方位都可以有 internal 目录,而不仅仅是在尖端目录中。

/internal 内部可以添加额外的包结构来区别组件间同享和私有的内部代码:

internal
├── app
│ ├── ctl
│ ├── server
│ └── task
└── pkg

其间 /internal/app 下寄存各个组件的逻辑代码,/internal/pkg 下寄存各组件间的同享代码。

/pkg

包括可导出的公共库,可以被其他项目引证。这意味着此目录下的代码可以被导入任何其他项目,被当作库程序来运用,所以将代码放到此目录前要慎重考虑,不要将私有代码放到此目录下。

Travis Jeffery 撰写了一篇文章解说了 pkginternal 目录运用主张,你可以进一步了解学习。

/configs

此目录寄存装备文件模板或默许装备。

前文讲规划项目目录的基本准则时说到目录名最好运用奇数方法,不过由于运用 configs 来寄存装备已经是约定俗成的事实标准,故此目录称号可以打破这项规划准则。

/test

可以用来寄存 e2e 测试和测试数据等。

关于较大的项目,有一个数据子目录更好一些。例如,假如需求 Go 在编译时忽略目录中的内容,则可以运用 /test/data/test/testdata 这样的目录称号。

别的 Go 还会忽略以 ._ 最初的目录或文件,因而可以更具灵活性的来命名测试数据目录。

deployments

用来寄存 IaaS、PaaS 体系和容器编列布置所需求的装备及模板(如:Docker-Compose,Kubernetes/Helm,Mesos,Terraform,Bosh)。

假如你的项目作为 Kubernetes 生态中的一员或运用 Kubernetes 布置,则主张命名为 /deploy,更加契合 Kubernetes 社区风格。

/third_party

外部辅助东西目录,fork 的代码和其他第三方东西(例如 Swagger UI)。比方咱们修改了某个开源的第三方项意图代码,使其满意当时项意图运用需求,就可以将修改后的代码放到 /third_party/fork 目录下进行保护。

/web

假如你打算在项目目录下包括配套的前端程序代码,则可以寄存到此目录。首要包括静态资源、前端代码、路由等。

假如你的项目仅供给 RESTful API,且前后端程序需求分开独立保护,则可以不需求此目录,主张将前端代码作为一个独立的项目存在。

项目办理相关目录

/init

包括体系初始化(systemd、upstart、sysv)和进程办理(runit、supervisord)等装备。这在非容器化布置的项目中非常有用。

别的还可以包括初始化代码,如数据库搬迁、缓存初始化等。

/scripts

寄存用于履行各种构建、安装、分析等操作的脚本。

根文件 /Makefile 可以引证这些脚本,使其变得更小、更易于保护。

/build

寄存程序构建和持续集成相关的文件。例如:

运用 /build/package 目录来寄存云(AMI),容器(Docker),操作体系(deb,rpm,pkg)软件包装备和脚本。

运用 /build/ci 目录来寄存 CI(travis、circle、drone)装备文件和脚本。

/tools

此项意图支持东西。这些东西可以从 /pkg/internal 目录导入代码。

/assets

项目运用的其他资源 (Image、CSS、JavaScript、SQL 文件等)。

/githooks

Git 相关的钩子寄存目录。

项目文档相关目录

/api

当时项目对外露出的 API 文档,如 OpenAPI/Swagger 标准文档、JSON Schema 文件、ProtoBuf 界说文件等。

api
└── openapi
    └── openapi.yaml
/docs

规划、开发和用户文档等(除 godoc 生成的文档)。

/examples

应用程序或公共库的示例。降低运用者的上手难度。

不主张运用的目录

/src

一些有 Java 或 Python 开发经验的开发者习气在项目中规划一个 /src 目录,但在 Go 言语中这是不引荐的做法。

前期的 Go 言语的项目都会被放置到 $GOPATH/src 目录下,假如项目中再有一个 /src 目录,那么项目终究的寄存的途径就显得比较奇怪:

$GOPATH/src/your_project/src/your_code.go

因而,请不要在一个 Go 项目中规划 /src 目录。

一些放在项目根目录下的文件

/README.md

README.md 是学习并运用项意图入口,是让用户了解项意图第一手资料。一个项意图 README.md 一般包括项目称号和简介、安装说明、运用说明、奉献方法、版权和答应等。

GitHub 也会默许解析 README.md 文件并渲染成 HTML 文档。

/Makefile

Makefile 是一个老牌的项目办理东西,主张在 Go 项目中都集成它。Makefile 语法可以参阅 跟我一起写 Makefile

/CHANGELOG

用于寄存项意图更新记录,如版本号、作者、更新内容等。假如嫌麻烦,还可以运用 git-chglog 或相似东西主动生成。

/CONTRIBUTING.md

假如你的项目是开源项目,则主张包括 /CONTRIBUTING.md 文件,用来说明怎么奉献代码、项目标准等,让第三方开发者更容易参与进来。

/LICENSE

开源项目必定要包括 /LICENSE,即开源答应证。没有开源答应证的项目,严格来讲不叫开源项目,怎么挑选开源答应证可以参阅我的另一篇文章 开源协议简介。

总结

经过上面的解说,终究咱们得到的项目目录结构如下:

project
├── CHANGELOG
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── README.md
├── api
│ └── openapi
│     └── openapi.yaml
├── assets
├── build
├── cmd
│ ├── ctl
│ │ └── main.go
│ ├── server
│ │ └── main.go
│ └── task
│     └── main.go
├── configs
├── deployments
├── docs
├── examples
├── githooks
├── init
├── internal
│ ├── app
│ │ ├── ctl
│ │ ├── server
│ │ └── task
│ └── pkg
├── pkg
├── scripts
├── test
├── third_party
├── tools
└── web

此目录结构首要参阅 golang-standards/project-layout 项目,和一些我自己的思考,终究总结出来。

经过运用以上供给的项目目录结构,可以协助开发者更好地办理和安排自己的代码,进步代码的可保护性和可扩展性。

以上介绍的目录结构比较合适中大型项目,假如你的项目比较小,则可以只运用 /cmd/internal/configs 等几个少数目录,其他目录根据需求再来创立。假如你的项目满足小,乃至不需求什么目录,直接采用平铺式代码结构(将所有文件都放在项目根目录下)即可。

别的,随着技能的不断迭代发展,如 DDD 正在流行起来,Go 社区对项目目录结构的探究也仍在持续,在可预见的未来,一个优异的 Go Web 项目目录结构的界说必定会被更新,等待下次可以分享更优异的目录结构规划。

P.S.

本文部分内容由 ChatGPT 生成,体会科技乐趣 :)。

参阅

github.com/golang-stan…
github.com/golang-stan…
github.com/danceyoung/…
travisjeffery.com/b/2019/11/i…