前言
无论我们用什么语言,做什么项目,都应该事先对项目的整体文件夹布局做长远考虑:什么文件应该放哪里,这其实十分重要,一个清晰简洁的项目结构让其他贡献者更容易上手,也让自身的维护与拓展更加方便(还能让开发者显得专业懂行)。Go生态圈里有一个项目的常用结构,它十分普遍且广受认可,今天在这里记录一下,以后新建项目时好当个cheatsheet来用。
顶层文件目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
.
├── Makefile
├── README.MD
├── api/ # api接口定义文件(protobuf-spec, http-spec, swagger.yaml...)
├── build/ # 安装包、容器与ci构建文件(Dockerfile, DEBIAN, travis...)
├── cmd/ # 入口代码
├── configs/ # 配置文件的模板
├── deployments/ # 部署相关配置和模板(Docker-Compose, K8s/Helm...)
├── docs/ # 文档
├── go.mod
├── internal/ # 具体业务代码
├── pkg/ # 可复用代码
├── scripts/ # 脚本
└── web/ # 前端工程目录
|
基本上挺self-explanatory的,下面介绍在结合整洁架构的理念时几个文件里面具体的内容。
cmd/
1
2
3
|
cmd
└── apiserver/
└── apiserver.go
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
package main
import (
"math/rand"
"os"
"runtime"
"time"
"github.com/midk9t/goproject/internal/apiserver"
)
func main() {
rand.Seed(time.Now().UTC().UnixNano())
if len(os.Getenv("GOMAXPROCS")) == 0 {
runtime.GOMAXPROCS(runtime.NumCPU())
}
apiserver.NewApp("goproject").Run()
}
|
cmd目录负责存放每个可编译成可执行程序的入口代码,如上面的apiserver就负责启动api进程。每个cmd里的包都必须是main包,且不包含太多具体业务逻辑,而是负责调用internal/和pkg/里具体的包来使服务运行。
pkg/
1
2
3
|
pkg
├── app/
└── log/
|
pkg目录负责存放一些可以给其他项目调用的,足够通用的包,如上面的app与log就是业务无关的项目工具包。
internal/
1
2
3
4
5
6
7
8
9
10
11
12
13
|
apiserver/
├── config/ # apiserver启动配置
├── controller/ # controller层
│ └── banana/
│ └── crud.go
├── domain/ # 领域层
│ └── banana.go # 模型定义
├── repo/ # 持久层
│ ├── fake/
│ └── mysql/
└── service/ # service层
└── banana/
└── bananaSrv.go
|
internal目录存放的就是项目核心代码啦,这里假设是常规的后端项目,并遵循Uncle Bob的整洁架构:
- controller层负责暴露接口并调用service和domain,处理输入校验与输出等对外的工作
- service层与domain层负责核心业务逻辑的执行
- domain层还负责存放领域对象的定义
- repo层负责持久化存储
Reference
本文主要用来当cheatsheet,方便随用随读,一些子目录(如api,deployment等)下具体的结构和整个项目结构的详细说明在这里:
06 | 目录结构设计:如何组织一个可维护、可扩展的代码目录?-极客时间
https://github.com/bxcodec/go-clean-arch
https://github.com/golang-standards/project-layout