Golang Project Layout

尹欣恬 February 17, 2025

先来看看冰岩内部大部分项目的通用结构

https://git.bingyan.net/lyt99/generator-bingyan-golang

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
├── docker-compose.yml
├── Dockerfile
├── env
│ └── config
├── README.md
└── src
├── config
│ └── config.go
├── controller
├── job
├── main.go
├── middleware
├── model
├── router
└── util
├── log
├── context
├── jwt.go
└── ......

也没有什么不好.jpg

golang-standards/project-layout

https://github.com/golang-standards/project-layout

想来分享一下 golang-standards/project-layout,它不是 Go 官方标准,然而,它是 Go 生态系统中一组常见的老项目和新项目的布局模式。

/cmd

每个应用程序的目录名应该与你想要的可执行文件的名称相匹配(例如,/cmd/myapp)。

作为整个项目程序的入口,通常有一个小的 main 函数,从 /internal/pkg 目录导入和调用代码,除此之外没有别的东西。大块的逻辑代码不应该出现在 cmd 中。

/internal

存放私有项目代码,web 项目中大部分业务逻辑代码都可放在该目录下。例如 mvc 架构中的 controller, jobs, middleware, model, router 等。

/pkg

外部应用程序可以使用的库代码。pkg 意味着第三方项目可以导入这些库,所以在这里放东西之前要三思:-)

如果应用程序项目规模较小,并且额外的嵌套并不能增加多少价值,那就不要使用它。当它变得足够大时,你的根目录会变得非常繁琐时 (尤其是当你有很多非 Go 应用组件时),请考虑一下。

/vendor

应用程序依赖项

vendor 目录是 Golang 从 1.5 版本开始引入的,为项目开发提供了一种离线保存第三方依赖包的方法。但是到了 Golang 1.11 之后,由于引入了 Module 功能,在运行 go build 时,优先引用的是 Module 依赖包的逻辑,所以当下较少使用 vendor 目录了

当然,你依然可以使用 go mod vendor 构建 vendor, 依赖项将先从 vendor 目录进行扫描。

/configs

配置文件模板或默认配置。

/scripts

放置脚本。

/build

打包和持续集成。

/build/package: 放置 dockerfile、操作系统( deb、rpm、pkg )包配置等

/build/ci:放置 ci 文件,如 .drone.yml

/deploy

docker-compose、kubernetes/helm、mesos、terraform、bosh 等

/test

额外的外部测试应用程序和测试数据。

/docs

设计和用户文档(除了 godoc 生成的文档之外)。

有关示例,请参阅 /docs 目录。

其他

除此之外,还包括

OpenAPI/Swagger 规范,JSON 模式文件,协议定义文件。

特定于 Web 应用程序的组件:静态 Web 资产、服务器端模板和 SPAs。

你的应用程序和/或公共库的示例。

外部辅助工具,分叉代码和其他第三方工具(例如 Swagger UI)。

Git hooks。

与存储库一起使用的其他资产(图像、徽标等)。

不应该拥有 /src?

来自 golang-standards/project-layout 的解释:

有些 Go 项目确实有一个 src 文件夹,但这通常发生在开发人员有 Java 背景,在那里它是一种常见的模式。如果可以的话,尽量不要采用这种 Java 模式。你真的不希望你的 Go 代码或 Go 项目看起来像 Java:-)

不要将项目级别 src 目录与 Go 用于其工作空间的 src 目录(如 How to Write Go Code 中所述)混淆。$GOPATH 环境变量指向你的(当前)工作空间(默认情况下,它指向非 windows 系统上的 $HOME/go)。这个工作空间包括顶层 /pkg, /bin/src 目录。你的实际项目最终是 /src 下的一个子目录,因此,如果你的项目中有 /src 目录,那么项目路径将是这样的: /some/path/to/workspace/src/your_project/src/your_code.go。注意,在 Go 1.11 中,可以将项目放在 GOPATH 之外,但这并不意味着使用这种布局模式是一个好主意。

以 k8s 项目架构为例

https://github.com/kubernetes/kubernetes

按照 golang-standards/project-layout 重构后的 sso

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
├── build
│ ├── ci
│ │ └── .drone.yml
│ └── package
│ ├── Dockerfile
│ └── Dockerfile-dev
├── cmd
│ └── sso
│ └── sso.go
├── configs
│ ├── configfile
│ └── rsa-key
├── deploy
│ ├── docker-compose.yml
│ └── log
│ ├── log -> log/log-2023-03-24
│ ├── log-2023-03-19
│ └── log-2023-03-24
├── docs
├── internal
│ ├── conf
│ ├── controller
│ ├── jobs
│ ├── middleware
│ ├── model
│ └── router
├── pkg
│ ├── jwt
│ ├── oauthcli
│ ├── oidc
│ └── util
├── go.mod
├── README.md
├── scripts
│ └── compose.sh
└── web
└── email_template.html