Golang 项目目录风格

总结的 Go Project 目录推荐风格。

出自项目 golang-standards/project-layout,去掉一些冗余信息之后成文。

写在前面:

  • 这里描述的风格是一些常见的项目的代码组织布局,并非官方标准,事实上官方也没有规定标准。
  • 其目的是通过共识减少协作中的沟通成本,以提高开发 / 传播效率。
  • 仅作为推荐,应该自由的取舍。
  • Go 1.14 以上请使用 Go Modules 管理项目。

概述

常见的目录结构:

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
38
39
├── LICENSE.md
├── Makefile
├── api
│   ├── swagger
│   └── protobuf
├── assets
├── build
│   ├── ci
│   └── package
├── cmd
│   ├── myapp1
│   └── myapp2
├── configs
├── deployments
├── docs
├── examples
├── githooks
├── go.mod
├── init
├── internal
│   ├── app
│   │ ├── myapp1
│   │   └── myapp2
│   └── pkg
│   ├── apppkg1
│   └── apppkg2
├── pkg
│   ├── mypkg1
│   └── mypkg2
├── scripts
├── test
├── third_party
├── tools
├── web
│   ├── app
│ │ └── api
│   ├── static
│   └── template
└── website

Go 核心代码相关目录

cmd

项目编译出的可执行文件的目录,一般来说 cmd 下每一个 dir 都应该对应一个可执行文件。

1
2
3
├── cmd
│   ├── myapp1
│   └── myapp2

注意:

  • cmd 中最好只防止程序的入口代码,保持 cmd 的代码简洁,通过调用 pkg 和 internal 目录下的代码来建立整个程序逻辑。
  • 一个子目录对应一个可执行文件。
  • 子目录名与可执行文件的名称相匹配 (例如,/cmd/myapp1)。
  • 在文件中只保留一个 main 函数是一种推荐的做法。

internal

用来存放非共享的代码。go 的引用机制决定了 intelnal 目录中的代码只能够被 intelnal 下的内部代码引用。

Go 1.4 关于 internal package 的说明

1
2
3
4
5
6
7
├── internal
│   ├── app
│   │ ├── myapp1
│   │   └── myapp2
│   └── pkg
│   ├── apppkg1
│   └── apppkg2

注意:

  • 用来存放非共享的代码。
  • intelnal 目录并不只局限于根目录下的 internal 目录,还可以是项目目录树的任何 internal 目录。
  • internal 下依然可以有语意化的目录组织形式,上例中 app 存放各 app 的代码,pkg 存放 app 之间的共享代码,但是这些共享代码不对项目外开放。

pkg

用来存放可以对外部共享的库代码。

1
2
3
├── pkg
│   ├── mypkg1
│   └── mypkg2

注意:

  • 供外部使用的代码最好具有完善的测试和文档。
  • 参考 Travis Jeffery 的 blog I'll take pkg over internal 更深入的理解 pkg /internal 的使用方法。

vendor

淘汰,不表。

服务应用程序目录

api

用来放置 API 的描述文件,如:OpenAPI/Swagger 文件,JSON Schema,protobuf 文件。

1
2
3
├── api
│   ├── swagger
│   └── protobuf

有关示例,请参见 /api 目录。

Web 应用程序目录

/web

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

1
2
3
4
5
├── web
│   ├── app
│ │ └── api
│   ├── static
│   └── template

通用应用目录

/configs

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

将你的 confdconsul-template 模板文件放在这里。

/init

系统初始化工具,如:systemd、process manager、supervisor、等配置

/scripts

构建、安装、分析等的脚本,这些脚本并不是被直接执行,而是应该在 Makefile 中被触发。

示例见 scripts 目录。

/build

构建和 CI 等。

1
2
3
├── build
│   ├── ci
│   └── package

注意:

  • package 目录中放置包配置脚本,如:docker,AMI,deb,pkg 之类。
  • ci 目录放置 ci 工具需要的配置和脚本。
  • 像是 travisCI 对位置要求较高的工具,可以尝试使用软连接将脚本链接到指定的位置。

/deployments

放置部署配置和脚本,如:docker-compose,kubernetes/helm,mesos,helm、mesos、terraform、bosh 等
在 kubernetes 的环境中,可能被命名为 deploy。

/test

放置外部测试和测试数据。

注意:

  • go 会忽略 /test/data/test/testdata 目录,可以用他们放置测试数据。
  • go 还会忽略 “.” 或 “_” 开头的文件或目录。

示例见 /test 目录。

其他目录

/docs

设计和用户文档 (不包含 godoc 生成的文档)。

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

/tools

这个项目的辅助工具。工具可以从 /pkg/internal 目录导入代码。

示例见 /tools 目录。

/examples

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

示例见 /examples 目录。

/third_party

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

/githooks

Git hooks。

/assets

与存储库一起使用的其他资源 (图像、logo 等)。

/website

如果你不使用 Github 页面,则在这里放置项目的网站数据。

有关示例,请参见 /website 目录。

不推荐的目录

/src

src 是很有 java 背景的文件夹,如果可以,尽量不要采用这种风格。


关于代码风格的一些参考

如果需要命名、格式和样式方面的帮助,运行 gofmtgolint

最好多看看 Go 代码风格的建议:

参见 Go Project Layout 了解更多的信息。

更多关于包的命名和组织以及其他代码结构的建议: