什么是一个明智的方式来布局一个Go项目
我有一个开始变得越来越复杂的项目,并希望以这种方式来减less文件系统的痛苦。
有什么有意义的吗?
2013年5月更新:正式文件位于“ 代码组织 ”部分
Go代码必须保存在工作区内。
工作区是一个目录层次结构,其根目录有三个目录:
-
src
包含组织成软件包的Go源文件(每个目录一个软件包), -
pkg
包含包对象,和 -
bin
包含可执行的命令。
go tool
构build源代码包,并将生成的二进制文件安装到pkg
和bin
目录中。
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月更新:请参阅Ben Johnson的 “ 在Go中构build应用程序 ”
该文章包含如下提示:
将你的二进制文件与你的应用程
将
main.go
文件和我的应用程序逻辑组合在一起会产生两个后果:
- 它使我的应用程序不能用作库。
- 我只能有一个应用程序二进制文件。
我发现解决这个问题的最好方法就是在我的项目中简单地使用“
cmd
”目录,其中的每个子目录都是应用程序二进制文件。
camlistore/ cmd/ camget/ main.go cammount/ main.go camput/ main.go camtool/ main.go
图书馆推动发展
将
main.go
文件移出根目录,可以从库的angular度构build应用程序。 您的应用程序二进制文件只是您应用程序库的一个客户端。有时您可能希望用户以多种方式进行交互,以便创build多个二进制文件。
例如,如果你有一个允许用户将数字加在一起的“adder
”包,你可能想要发布一个命令行版本以及一个网页版本。
您可以通过像这样组织项目来轻松完成此任务:
adder/ adder.go cmd/ adder/ main.go adder-server/ main.go
用户可以用省略号“go get”来安装你的“加法器”应用程序二进制文件:
$ go get github.com/benbjohnson/adder/...
瞧,你的用户安装了“
adder
”和“adder-server
”!
不要疯狂分包
通常我的项目types都是非常相关的,所以从可用性和API的angular度来看,它更好。
这些types还可以利用它们之间的未导出的调用来保持API小而清晰。
- 在每个文件中将相关types和代码组合在一起。 如果你的types和function组织的很好,那么我发现文件往往在200到500 SLOC之间。 这可能听起来很多,但我觉得很容易导航。 1000 SLOC通常是我单个文件的上限。
- 在文件顶部组织最重要的types,并添加对文件底部重要性降低的types。
- 一旦你的应用程序开始获得10,000 SLOC以上,你应该认真评估它是否可以分解成更小的项目。
注意:最后的做法并不总是好的:
对不起,我只是不能同意这种做法。
将types分离为文件有助于代码pipe理,可读性,维护性,可testing性。
它也可以确保单一的责任和开放/封闭的原则… …
不允许循环依赖的规则是强制我们有一个清晰的包结构。
(2013年2月份,仅针对src
)
您可以在“ GitHub代码布局 ”中find经典布局:
应用程序和两个库都在Github上,每个都在它自己的仓库中。
$GOPATH
是项目的根源 – 你的每个Github$GOPATH
将在$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签出的根目录。
这引起了一些批评,但在这个reddit页面 :
我强烈build议不要按照自己的方式构build回购协议,它会打破“
go get
”,这是关于Go的最有用的东西之一。
为那些懂Go的人编写代码要好得多,因为他们最有可能是编译它的人。
而对于不这样做的人,他们至less会感受到这种语言。把主包放在回购的根。
让资产在一个子目录中(保持整洁)。
将代码的肉放在一个子包中(以防有人想在二进制文件之外重用)。
在回购的根目录中包含一个设置脚本,因此很容易find。下载,构build,安装和设置仍然只有两个步骤:
- “
go get <your repo path>
”:下载并安装去代码,与资产的子目录$GOPATH/<your repo path>/setup.sh
:将资产分配到正确的位置并安装服务
我假设用'项目'你不是指一个Go软件包,而是一个你开发的软件。 否则,你可以在这里和这里得到帮助。 然而,与为Go编写软件包没有多大区别:使用软件包,为每个软件包创build一个文件夹,并将这些软件包合并到应用程序中。
为了build立自己的意见,你可以看看github上的Go存储库: https : //github.com/trending/go 。 着名的例子是凯利和宙斯 。
最stream行的scheme可能是在他们自己的目录中有一个主要的Go文件和许多模块和子模块。 如果你有许多元文件(文档,许可证,模板,…),你可能想把源代码放到一个子目录中。 这就是我迄今为止所做的。
Golang的作者提出了一个推荐的方法 ,它定义了如何布局代码,以便与go工具最好地协作,并支持源代码控制系统
我已经描述了在这里设置Go环境的方法: http : //blog.tideland.biz/2013-07-09-go-environment-setup 。 它还展示了如何处理第三方软件包。