项目组织结构

参见 标准 Go 项目布局 以了解更多背景信息。

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

一篇关于面向包的设计和架构分层的中文文章:

目录

/cmd

存放项目的主要程序。

每个程序的目录名称应与期望的最终的可执行文件的名称相匹配(例如 /cmd/myapp)。

不要在此目录中放大量代码。如果你认为这些代码可以被复用,那么它应该在/pkg目录中。如果代码不能被复用,或者你不希望它被别人复用,那么请把这些代码放在/internal目录下。你往往无法预测别人会基于你的代码做什么,所以请明确自己的意图,并将代码放到合适的位置。

通常会有一个main函数,导入并调用/internal/pkg目录中的代码,而不是其他函数。

/internal

存放私有程序和库代码。这里是你不希望别人在其应用程序或库中导入的代码。请注意,这种项目组织结构是由 Go 编译器强制执行的。更多细节请参见 Go 1.4 release notes 。并不是只能在根目录放置internal,任何级别的目录下都可以建立internal目录。

你可以选择性的给你的 internal 包添加一些额外的结构,以分离共享和非共享的内部代码。这不是必须的(特别是对于较小的项目),但可以使包的用途一目了然。应用程序相关代码可以放在/internal/app目录下(例如 /internal/app/myapp),被其他程序复用的代码可以放在/internal/pkg目录下(例如 /internal/pkg/myprivlib)。

/pkg

存放可以被外部应用程序使用的库代码(例如 /pkg/mypubliclib)。 其他项目会 import 这些库,并且希望它们能够正常运作。所以在你把代码放在这里之前请三思而后行 :-) 请注意,internal目录是确保你的私有包不被他人导入的更好的方法,因为它是由 Go 强制执行的。 /pkg目录是一个很好的方式,用来明确表达该目录中的代码可以被他人安全使用。Travis Jeffery 发表的I’ll take pkg over internal博文介绍了pkginternal,以及它们的使用场景。

当你的根目录包含大量的非 Go 组件和目录时,它也可以作为一种将 Go 代码分组在同一个地方的方法,以更容易运行各种 Go 工具(正如在这些会谈中提到的:来自 GopherCon EU 2018 的Best Practices for Industrial ProgrammingGopherCon 2018: Kat Zien - How Do You Structure Your Go Apps以及GoLab 2018 - Massimiliano Pippi - Project layout patterns in Go)。

如果你的项目非常小,额外的嵌套层次并没有什么意义,除非你真的想这样做:-),完全可以不用它。建议在你的项目越来越大、根目录变得杂乱、特别是当你有很多非 Go 应用组件的时候,再考虑使用 /pkg

pkg目录的由来:旧的 Go 源代码曾经使用pkg来存放包,然后社区中的各种 Go 项目开始复制这种模式(更多背景详见Brad Fitzpatrick 的 tweet )。

/vendor

存放程序依赖(手动管理或通过依赖管理工具,如新的内置的Go Modules特性)。go mod vendor命令将为你创建/vendor目录。请注意,如果你的 Go 版本大于等于 1.14,go build命令默认开启mod=vendor;否则可能要手动开启。

如果你正在编写一个库,请不要提交程序的依赖关系。

请注意,自从1.13 版本 Go 也启用了模块代理功能(默认使用https://proxy.golang.org作为其模块代理服务器)。 详情可参阅这里,看看它是否符合你所有的要求。如果符合,就不需要vendor目录。

通用程序目录

/hack

/hack目录包含许多脚本,确保 DevStream 的持续发展。

/build

打包(构建)和持续集成。

把你的云(AMI)、容器(Docker)和操作系统(deb、rpm、pkg)软件包配置和脚本放在/build/package目录下。

把你的 CI(travis, circle, drone)配置和脚本放在/build/ci目录下。请注意,一些 CI 工具(例如Travis CI)对配置文件的位置非常挑剔。可以试着把配置文件放在/build/ci目录中,再链接到 CI 工具所期望的位置(如果可能的话)。

/test

额外的外部测试程序和测试数据。你可以随心所欲地构建/test目录。对于较大的项目,很有必要建立一个数据子目录是。例如,如果你需要 Go 忽略该目录中的内容,可以创建/test/data/test/testdata目录。注意,Go 也会忽略以”.”或”_“开头的目录与文件,所以你可以灵活地命名测试数据目录。

其他目录

/docs

存放设计和用户文件(除 godoc 生成的文件)。

/examples

存放应用程序与库的示例。

不应该存在的目录

/src

有些 Go 项目确实有一个src文件夹,但这通常是由于开发人员之前是 Java 程序员,这在 Java 中是一种常见的模式。但请尽可能不要采用这种 Java 模式,不要把你的 Go 代码或 Go 项目写成 Java 的样子:-)

不要把项目级的/src目录与如何编写Go代码中描述的 Go 用于其工作区的/src目录混淆。$GOPATH环境变量指向你的(当前)工作空间(在非 Windows 系统上默认指向$HOME/go)。这个工作空间包括顶层的/pkg/bin/src目录。你的实际项目其实是/src下的一个子目录,所以如果你的项目中有/src目录,项目路径看起来会是这样:/some/path/to/workspace/src/your_project/src/your_code.go。请注意,在 Go 1.11中,你的项目有可能在GOPATH之外,但这不意味着使用这种项目组织结构是一个好主意。

徽章

  • Go Report Card - 它会采用gofmtgo vetgocyclogolintineffassignlicensemisspell来扫描你的代码。记得把 github.com/golang-standards/project-layout替换为你的项目地址。

    Go Report Card

  • pkg.go.dev - pkg.go.dev 是一个新的 Go 语言的 package 和 module 的文档中心。你可以用以下方法创建一个徽章

    PkgGoDev

  • Release - 它将显示你的项目的最新版本号,改变 github 链接以指向你的项目。

    Release