布局 Go 项目的明智方法是什么

我有一个开始变得更加复杂的项目,希望以这样一种方式来布置文件系统,以减少痛苦。

Are there some good examples out there of what makes sense?

42974 次浏览

我假设你说的“项目”并不是一个 Go 软件包,而是一个你自己开发的软件。 否则,你可以得到帮助 给你给你。 然而,这与为 Go 编写软件包没有太大区别: 使用软件包,为每个软件包创建一个文件夹,然后在应用程序中组合这些软件包。

要建立自己的观点,您可以查看 github: https://github.com/trending/go上的趋势 Go 仓库。值得注意的例子是 < a href = “ https://github.com/cayleygraph/cayley”rel = “ nofollow noReferrer”> cayley 和 宙斯

最流行的方案可能是在它们自己的目录中有一个主 Go 文件和许多模块和子模块。如果您有许多元文件(doc、許可證、模板、 ...) ,您可能需要将源代码放入一个子目录中。目前为止我就是这么做的。

2013年5月更新: 正式文件在“ 代码组织”部分

Go 代码必须保存在 workspace中。
工作区是一个目录层次结构,其根目录有三个:

  • src contains Go source files organized into packages (one package per directory),
  • pkg包含包对象,以及
  • bin包含可执行命令。

go tool构建源包并将生成的二进制文件安装到 pkgbin目录。

src子目录通常包含多个版本控制存储库(如 Git 或 Mercurial) ,它们跟踪一个或多个源包的开发。

bin/
streak                         # command executable
todo                           # command executable
pkg/
linux_amd64/
code.google.com/p/goauth2/
oauth.a                # package object
github.com/nf/todo/
task.a                 # package object
src/
code.google.com/p/goauth2/
.hg/                       # mercurial repository metadata
oauth/
oauth.go               # package source
oauth_test.go          # test source

2014年7月更新: 见 本 · 约翰逊的“ < strong > 构建 Go 中的应用程序

这篇文章包含了以下建议:

从应用程序中分离二进制文件

main.go文件和我的应用程序逻辑组合在同一个包中有两个结果:

  • 它使我的应用程序不能作为库使用。
  • 我只能有一个二进制应用程序。

我发现解决这个问题的最好方法是在我的项目中简单地使用“ cmd”目录,其中每个子目录都是应用程序二进制文件。

camlistore/
cmd/
camget/
main.go
cammount/
main.go
camput/
main.go
camtool/
main.go

库驱动的开发

main.go文件移出根目录允许您从库的角度构建应用程序。应用程序二进制文件只是应用程序库的客户端。

Sometimes you might want users to interact in multiple ways so you create multiple binaries.
例如,如果您有一个“ adder”软件包,允许用户将数字相加,您可能希望发布命令行版本以及 Web 版本。
您可以通过以下方式轻松地组织您的项目:

adder/
adder.go
cmd/
adder/
main.go
adder-server/
main.go

用户可以使用省略号“ go get”安装您的“ Adder”应用程序二进制文件:

$ go get github.com/benbjohnson/adder/...

瞧,您的用户已经安装了“ adder”和“ adder-server”!

不要疯狂地使用子包

Usually my project’s types are all very related so it fits better from a usability and API standpoint.
这些类型还可以利用它们之间未导出的调用,从而保持 API 的小型化和清晰化。

  1. 在每个文件中将相关类型和代码分组在一起。如果您的类型和函数组织良好,那么我发现文件往往介于200和500 SLOC 之间。这可能听起来很多,但我发现它很容易导航。1000 SLOC 通常是我对单个文件的上限。
  2. 将最重要的类型组织在文件的顶部,并将重要性递减的类型添加到文件的底部。
  3. 一旦您的应用程序开始获得超过10,000 SLOC,您应该认真地评估它是否可以分解成更小的项目。

Note: that last practice isn't always good:

对不起,我不能同意这种做法。
将类型与文件分离有助于代码管理、可读性、可维护性和可测试性。
它也可以确保单一责任和遵循开放/封闭的原则..。
不允许循环依赖的规则是强制我们有一个清晰的包结构。


(另选2013年2月,仅关于 src)
你可以在“ GitHub Code Layout”中找到经典的布局:

这个应用程序和两个库都位于 Github 上,每个库都有自己的存储库。
$GOPATH是该项目的根源-您的每个 Github 回购将签出几个文件夹以下的 $GOPATH

Your code layout would look like this:

$GOPATH/
src/
github.com/
jmcvetta/
useless/
.git/
useless.go
useless_test.go
README.md
uselessd/
.git/
uselessd.go
uselessd_test.go
README.md

src/github.com/jmcvetta/下的每个文件夹都是一个单独的 git 签出的根。

不过,在这次 Reddit 主页会议上,这招致了一些批评:

我强烈建议不要构造回购的方式,你有,它会打破“ go get”,这是最有用的事情之一,围棋。
为那些知道 Go 的人编写代码要好得多,因为他们最有可能是编译它的人。
而对于那些不懂英语的人来说,他们至少可以感受一下英语。

将主包放在回购的根目录中。
将资产放在一个子目录中(以保持整洁)。
Keep the meat of the code in a subpackage (in case anyone wants to reuse it outside your binary).
在回购的根目录中包含一个安装脚本,这样很容易找到。

下载、构建、安装和设置仍然只需要两个步骤:

  • go get <your repo path>”: 下载并安装 go 代码,其中包含资产的子目录
  • $GOPATH/<your repo path>/setup.sh: 将资产分配到正确的位置并安装服务

Golang 的作者提供了一个 建议的方法,它定义了如何布局代码,使其能够最好地与 go 工具一起工作,并支持源代码控制系统

你也许应该看看这份回购协议。它展示了如何构建 Go 应用程序的许多想法: https://github.com/golang-standards/project-layout