这是Go应用程序项目的基本布局。不是核心Go开发团队定义的官方标准;但是,这是Go生态系统中的一组常见的历史和新兴项目布局模式。其中一些模式比其他模式更受欢迎。它还具有许多小的增强功能,以及任何足够大的实际应用程序共有的几个支持目录。
如果您想学习Go,或者您自己构建PoC或玩具项目,则此项目布局实在是太过分了。从一个非常简单的事情开始(一个main.go文件绰绰有余)。随着项目的增长,请记住,确保您的代码结构合理非常重要,否则最终将导致混乱的代码具有很多隐藏的依赖关系和全局状态。当有更多的人从事项目时,您将需要更多的结构。在那时候,重要的是要引入一种管理软件包/库的通用方法。当您拥有一个开源项目时,或者当您知道其他项目从项目存储库中导入代码时,拥有私有(aka内部)包和代码就很重要。克隆存储库,保留您需要的内容,然后删除其他所有内容!仅仅因为它在那里并不意味着您必须全部使用它。这些模式均未在每个项目中使用。甚至供应商模式也不是通用的。
有了Go 1.14,Go模块终于可以投入生产了。除非您有特定的原因不使用Go Modules,否则请使用Go Modules;如果这样做,则无需担心$ GOPATH和项目放置位置。回购中的基本go.mod文件假定您的项目托管在Github上,但这不是必需的。模块路径可以是任何东西,尽管第一个模块路径组件的名称中应带有点(当前版本的Go不再强制使用该点,但是,如果您使用的是稍旧的版本,则在构建失败时不会感到惊讶)它)。如果您想了解更多信息,请参见问题37554和32819。
该项目布局是有意通用的,并且不会尝试施加特定的Go包结构。
这是社区的努力。如果看到新的模式,或者认为需要更新现有模式之一,则打开一个问题。
如果需要命名,格式和样式方面的帮助,请先运行gofmt和golint。另外,请务必阅读以下Go代码样式指南和建议:
- https://talks.golang.org/2014/names.slide
- https://golang.org/doc/effective_go.html#names
- https://blog.golang.org/package-names
- https://github.com/golang/go/wiki/CodeReviewComments
- Style guideline for Go packages (rakyll/JBD)
有关其他背景信息,请参见转到项目布局。
有关命名和组织软件包以及其他代码结构建议的更多信息:
- GopherCon EU 2018: Peter Bourgon - Best Practices for Industrial Programming
- GopherCon Russia 2018: Ashley McNamara + Brian Ketelsen - Go best practices.
- GopherCon 2017: Edward Muller - Go Anti-Patterns
- GopherCon 2018: Kat Zien - How Do You Structure Your Go Apps
Go 目录
/cmd
该项目的主要应用。
每个应用程序的目录名称应与您想要的可执行文件的名称匹配(例如,“ / cmd / myapp”)。
不要在应用程序目录中放置过多代码。 如果您认为该代码可以导入并在其他项目中使用,那么它应该位于/ pkg
目录中。 如果该代码不可重用,或者您不希望其他人重用它,则将该代码放在/ internal
目录中。 您会惊讶于其他人会做什么,因此要明确您的意图!
通常有一个小的main函数可以从/ internal和/ pkg目录中导入并调用代码,而没有别的。
查看 /cmd
目录获取更多示例。
/internal
私有应用程序和库代码。 这是您不希望其他人在其应用程序或库中导入的代码。 请注意,此布局模式由Go编译器本身强制执行。 有关更多详细信息,请参见Go 1.4发行说明。 请注意,您不限于顶层内部目录。 在项目树的任何级别上,您都可以具有多个内部目录。
您可以选择向内部软件包中添加一些额外的结构,以分隔共享和非共享内部代码。 它不是必需的(尤其是对于较小的项目),但是最好有视觉提示来显示包装的预期用途。 您的实际应用程序代码可以放在/ internal / app目录(例如/ internal / app / myapp)中,而这些应用程序共享的代码可以在/ internal / pkg目录中(例如/ internal / pkg / myprivlib)。
/pkg
外部应用程序可以使用的库代码(例如/ pkg / mypubliclib)。 其他项目将导入这些库,希望它们能正常工作,因此在将某些内容放到这里之前,请三思:-)注意,内部目录是确保您的私有软件包不可导入的更好方法,因为它由Go强制执行。 / pkg目录仍然是明确传达该目录中的代码可被他人安全使用的好方法。 Travis Jeffery撰写的关于内部博客的pkg文章将很好地概述了pkg和内部目录以及何时使用它们。
当您的根目录包含大量非Go组件和目录时,这也是一种将Go代码分组到一个位置的方法,这使得运行各种Go工具变得更加容易(如在这些演讲中提到的那样:GopherCon EU 2018的工业编程最佳实践)GopherCon 2018: Kat Zien - How Do You Structure Your Go Apps and GoLab 2018 - Massimiliano Pippi - Project layout patterns in Go).
如果要查看哪个流行的Go存储库使用此项目布局模式,请参见/ pkg目录。 这是一种常见的布局模式,但未被普遍接受,并且Go社区中的某些人不推荐这样做。
如果您的应用程序项目很小,并且嵌套的额外层次不会增加太多价值(除非您真的想要:-),请不要使用它。 当它变得足够大并且您的根目录变得非常繁忙时(特别是如果您有很多非Go应用程序组件),请考虑一下。
/vendor
应用程序依赖项(手动或通过您喜欢的依赖项管理工具(如新的内置Go模块功能)进行管理)。 go mod vendor命令将为您创建/ vendor目录。 请注意,如果您不使用默认情况下处于启用状态的Go 1.14,则可能需要在go build命令中添加-mod = vendor标志。
如果要构建库,请不要提交应用程序依赖项。
请注意,自1.13开始,Go还启用了模块代理功能(默认情况下使用https://proxy.golang.org作为其模块代理服务器)。 在此处阅读有关它的更多信息,以了解它是否符合您的所有要求和约束。 如果是这样,那么您根本不需要供应商目录。
服务应用程序目录
/api
OpenAPI / Swagger规范,JSON模式文件,协议定义文件。
有关示例,请参见/ api目录。
Web 应用程序目录
/web
Web应用程序特定的组件:静态Web资产,服务器端模板和SPA。
通用应用程序目录
/configs
配置文件模板或默认配置。
将您的confd
或consul-template
模板文件放在此处。
/init
系统初始化(systemd,upstart,sysv)和进程管理器/主管(runit,supervisor)配置。
/scripts
用于执行各种构建,安装,分析等操作的脚本。
这些脚本使根级别的Makefile变得小而简单(例如https://github.com/hashicorp/terraform/blob/master/Makefile)。
有关示例,请参见/ scripts目录。
/build
包装和持续集成。
将您的云(AMI),容器(Docker),操作系统(deb,rpm,pkg)软件包配置和脚本放在/ build / package目录中。
将您的CI(travis,circle,drone)配置和脚本放在/ build / ci目录中。 请注意,某些配置项工具(例如Travis CI)对于其配置文件的位置非常挑剔。 尝试将配置文件放在/ build / ci目录中,将它们链接到CI工具期望它们的位置(如果可能)。
/deployments
IaaS,PaaS,系统和容器编排部署配置和模板(docker-compose,kubernetes / helm,mesos,terraform,bosh)。 请注意,在某些存储库中(尤其是使用kubernetes部署的应用程序),该目录称为/ deploy。
/test
其他外部测试应用程序和测试数据。 随时根据需要构建/ 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
与资源库一起使用的其他资产(图像,徽标等)。
/website
如果您不使用Github页面,则在这里放置项目的网站数据。
有关示例,请参见/ website目录。
您不应该拥有的目录
src
有些Go项目确实有一个src文件夹,但通常是在开发人员来自Java世界(通常是Java模式)时发生的。 如果可以帮助自己,请尝试不要采用此Java模式。 您真的不希望您的Go代码或Go项目看起来像Java :-)
不要将项目级别的/ src目录与Go用于其工作区的/ src目录混淆,如如何编写Go代码中所述。 $ GOPATH环境变量指向您(当前)的工作空间(默认情况下,它指向非Windows系统上的$ HOME / go)。 此工作空间包括顶级/ pkg,/ bin和/ src目录。 实际的项目最终是/ src下的子目录,因此,如果项目中有/ src目录,则项目路径将如下所示:/ some / path / to / workspace / src / your_project / src / your_code。 走。 请注意,使用Go 1.11,可以将项目放在GOPATH之外,但这并不意味着使用此布局模式是个好主意。
参考文档: