我有一个开始变得更加复杂的 go 项目,并且希望以这样一种方式来布置文件系统以减少痛苦。
有没有一些很好的例子来说明什么是有意义的?
Go 代码必须保存在工作区中。 工作区是一个目录层次结构,其根目录包含三个目录:
src
pkg
bin
在go tool构建源码包和安装产生的二进制文件的pkg和bin目录。 该src子目录通常包含多个版本控制存储库(例如 Git 或 Mercurial),用于跟踪一个或多个源包的开发。
在go tool构建源码包和安装产生的二进制文件的pkg和bin目录。
go tool
该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
那篇文章包括以下提示:
将main.go文件和我的应用程序逻辑组合在同一个包中有两个结果: 它使我的应用程序无法用作库。 我只能有一个应用程序二进制文件。 我发现解决这个问题的最好方法是cmd在我的项目中简单地使用一个“ ”目录,其中的每个子目录都是一个应用程序二进制文件。
将main.go文件和我的应用程序逻辑组合在同一个包中有两个结果:
main.go
我发现解决这个问题的最好方法是cmd在我的项目中简单地使用一个“ ”目录,其中的每个子目录都是一个应用程序二进制文件。
cmd
camlistore/ cmd/ camget/ main.go cammount/ main.go camput/ main.go camtool/ main.go
将main.go文件从根目录中移出允许您从库的角度构建应用程序。您的应用程序二进制文件只是应用程序库的客户端。 有时您可能希望用户以多种方式进行交互,因此您可以创建多个二进制文件。 例如,如果您有一个“ adder”包,可以让用户将数字加在一起,您可能希望发布命令行版本和网络版本。 你可以通过像这样组织你的项目来轻松地做到这一点:
将main.go文件从根目录中移出允许您从库的角度构建应用程序。您的应用程序二进制文件只是应用程序库的客户端。
有时您可能希望用户以多种方式进行交互,因此您可以创建多个二进制文件。 例如,如果您有一个“ adder”包,可以让用户将数字加在一起,您可能希望发布命令行版本和网络版本。 你可以通过像这样组织你的项目来轻松地做到这一点:
adder
adder/ adder.go cmd/ adder/ main.go adder-server/ main.go
用户可以使用省略号通过“go get”安装“adder”应用程序二进制文件:
$ go get github.com/benbjohnson/adder/...
瞧,您的用户安装了“ adder”和“ adder-server”!
adder-server
通常我的项目类型都非常相关,因此从可用性和 API 的角度来看它更适合。 这些类型还可以利用它们之间未导出的调用来保持 API 小而清晰。 在每个文件中将相关类型和代码组合在一起。如果您的类型和函数组织得很好,那么我发现文件往往在 200 到 500 SLOC 之间。这听起来可能很多,但我发现它很容易导航。1000 SLOC 通常是我对单个文件的上限。 在文件顶部组织最重要的类型,并在文件底部添加重要性递减的类型。 一旦您的应用程序开始超过 10,000 SLOC,您就应该认真评估它是否可以分解为更小的项目。
通常我的项目类型都非常相关,因此从可用性和 API 的角度来看它更适合。 这些类型还可以利用它们之间未导出的调用来保持 API 小而清晰。
注意:最后的做法并不总是好的:
对不起,我不能同意这种做法。 将类型分离到文件有助于代码管理、可读性、可维护性和可测试性。 它还可以确保单一职责和遵循开放/封闭原则...... 不允许循环依赖的规则是强制我们有一个清晰的包结构。
您可以找到“GitHub 代码布局中说明的经典布局:
该应用程序和两个库都位于 Github 上,每个库都在自己的存储库中。 $GOPATH是项目的根 - 您的每个 Github 存储库都将在下面的几个文件夹中检出$GOPATH。 您的代码布局如下所示:
该应用程序和两个库都位于 Github 上,每个库都在自己的存储库中。 $GOPATH是项目的根 - 您的每个 Github 存储库都将在下面的几个文件夹中检出$GOPATH。
$GOPATH
您的代码布局如下所示:
$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 checkout 的根目录。
src/github.com/jmcvetta/
不过,在这个reddit 页面中,这引起了一些批评:
我强烈建议不要按照你的方式构建 repo,它会破坏“ go get”,这是 Go 最有用的东西之一。 为了解 Go 的人编写代码要好得多,因为他们最有可能是编译它的人。 而对于那些不这样做的人,他们至少会感受到这种语言。 将主包放在 repo 的根目录中。 将资产放在子目录中(以保持整洁)。 将代码的内容保存在一个子包中(以防有人想在你的二进制文件之外重用它)。 在 repo 的根目录中包含一个设置脚本,以便于查找。 下载、构建、安装和设置仍然只有两步过程: ” go get <your repo path>”: 下载并安装 go 代码,带有资产的子目录 $GOPATH/<your repo path>/setup.sh:将资产分配到正确的位置并安装服务
我强烈建议不要按照你的方式构建 repo,它会破坏“ go get”,这是 Go 最有用的东西之一。 为了解 Go 的人编写代码要好得多,因为他们最有可能是编译它的人。 而对于那些不这样做的人,他们至少会感受到这种语言。
go get
将主包放在 repo 的根目录中。 将资产放在子目录中(以保持整洁)。 将代码的内容保存在一个子包中(以防有人想在你的二进制文件之外重用它)。 在 repo 的根目录中包含一个设置脚本,以便于查找。
下载、构建、安装和设置仍然只有两步过程:
go get <your repo path>
$GOPATH/<your repo path>/setup.sh