什么是布局Go项目的明智方式 [英] What is a sensible way to layout a Go project

查看:137
本文介绍了什么是布局Go项目的明智方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个开始变得越来越复杂的项目,并且希望以减少痛苦的方式创建文件系统。

有没有好的例子有什么有意义的吗?

解决方案

2013年5月更新:官方文档位于代码组织


Go代码必须保存在工作空间中。

工作空间是一个目录层次结构,其根目录下有三个目录:




  • src 包含组织到包中的Go源文件(每个目录一个包),
  • pkg 包含包对象,并且
  • bin 包含可执行命令。




go工具构建源代码包并将生成的二进制文件安装到t中他 pkg bin 目录。



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




  bin / 
streak#命令可执行文件
todo#命令可执行文件
pkg /
linux_amd64 /
code.google.com/p/goauth2/
oauth.a#包对象
github.com/nf/todo/
task.a#包对象
src /
code.google.com/p/goauth2/
.hg /#mercurial存储库元数据
oauth /
oauth.go#包源代码
oauth_test.go #test source






2014年7月更新: a href =https://medium.com/@来自在Go中构建应用程序 中的应用程序,本应用程序中的应用程序本约翰逊



该文章包括如下提示:



您的应用程序二进制文件




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


  • 它使我的应用程序不能用作库。

  • 我只能有一个应用程序二进制文件。



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




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



库驱动开发




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



有时您可能希望用户以多种方式进行交互,以便创建多个二进制文件。

例如,如果你有一个 adder 包,它允许用户将数字加在一起,你可能想要发布一个命令行版本以及一个web版本。 >
您可以通过以下方式轻松完成此项目:




 加法器/ 
adder.go
cmd /
加法器/
main.go
加法器/服务器
main.go


用户可以使用省略号go get安装adder应用程序二进制文件:




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




瞧,你的用户有加法器 adder-server 已安装!




不要对子包感到疯狂




通常我的项目类型是所有非常相关,所以它从适用性和API的角度来说更适合。

这些类型还可以利用它们之间的未导出的调用来保持API小而清晰。


  1. 在每个文件中将相关类型和代码组合在一起。如果你的类型和功能组织良好,那么我发现文件的大小通常在200到500 SLOC之间。这可能听起来很多,但我觉得很容易导航。 1000 SLOC通常是我单个文件的上限。

  2. 在文件顶部组织最重要的类型,并添加对文件底部重要性降低的类型。
  3. >
  4. 一旦您的应用程序开始获得10,000 SLOC以上,您应该认真评估它是否可以分解为更小的项目。


注意:最后一种做法并不总是很好:


对不起,我不能同意这个练习。

分离类型到文件有助于代码管理,可读性,维护性,可测试性。

它也可以确保单个责任和开放/关闭原则的后续行为。

不允许循环依赖的规则是强制我们有一个清晰的包结构。






(备选2013年2月,仅限于 src

您可以找到经典版式illustra GitHub代码布局


应用程序和两个库都位于Github上,每个库都位于其自己的存储库中。 c>是项目的根目录 - 你的每个Github仓库都会被签出到 $ GOPATH 以下的几个文件夹中。

您的代码布局看起来像这样:



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




src / git下的每个文件夹hub.com/jmcvetta / 是单独的git签出的根目录。

虽然引起了一些批评,但在 reddit页面


我强烈建议不要构建回购如果你有这种方式,它会打破去获取,这是Go最有用的东西之一。

写你的代码给那些了解Go的人,因为他们很可能是编译它的人。

对于那些不知道的人,他们至少会感受到这种语言。 p>

将主包放入回购站的根目录中。
将资产放在子目录中(以保持整洁)。
将代码的肉放在一个子包中(以防有人想在二进制文件之外重用它)。
在回购的根目录中包含一个设置脚本,因此很容易找到。



这只是一个两步骤的过程oad,build,install,and setup。:




  • go get your repo path> :下载并安装代码,并使用资产的子目录
  • $ GOPATH /<您的回购路径> /setup.sh :将资产分配到正确的位置并安装服务


I have a go project that is starting to become more complex, and want to lay the filesystem out in such a way to reduce pain.

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

解决方案

Update May 2013: the official documentation is in the section "Code organization"

Go code must be kept inside a workspace.
A workspace is a directory hierarchy with three directories at its root:

  • src contains Go source files organized into packages (one package per directory),
  • pkg contains package objects, and
  • bin contains executable commands.

The go tool builds source packages and installs the resulting binaries to the pkg and bin directories.

The src subdirectory typically contains multiple version control repositories (such as for Git or Mercurial) that track the development of one or more source packages.

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


Update July 2014: see "Structuring Applications in Go" from Ben Johnson

That article include tips like:

Separate your binary from your application

combining the main.go file and my application logic in the same package has two consequences:

  • It makes my application unusable as a library.
  • I can only have one application binary.

The best way I’ve found to fix this is to simply use a "cmd" directory in my project where each of its subdirectories is an application binary.

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

Library driven development

Moving the main.go file out of your root allows you to build your application from the perspective of a library. Your application binary is simply a client of your application’s library.

Sometimes you might want users to interact in multiple ways so you create multiple binaries.
For example, if you had an "adder" package that that let users add numbers together, you may want to release a command line version as well as a web version.
You can easily do this by organizing your project like this:

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

Users can install your "adder" application binaries with "go get" using an ellipsis:

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

And voila, your user has "adder" and "adder-server" installed!

Don’t go crazy with subpackages

Usually my project’s types are all very related so it fits better from a usability and API standpoint.
These types can also take advantage of calling unexported between them which keeps the API small and clear.

  1. Group related types and code together in each file. If your types and functions are well organized then I find that files tend to be between 200 and 500 SLOC. This might sound like a lot but I find it easy to navigate. 1000 SLOC is usually my upper limit for a single file.
  2. Organize the most important type at the top of the file and add types in decreasing importance towards the bottom of the file.
  3. Once your application starts getting above 10,000 SLOC you should seriously evaluate whether it can be broken into smaller projects.

Note: that last practice isn't always good:

Sorry I just cant agree with this practice.
Separating type to files helps code management, readability, maintenancability, testability.
It may also ensure single responsibility and the follow of open/closed principle…
The rule for not allowing circular dependency is to force we have a clear structure of the packages.


(Alternative February 2013, regarding src only)
You can find the classic layout illustrated in "GitHub Code Layout":

The app and both libraries live on Github, each in its own repository.
$GOPATH is the root of the project - each of your Github repos will be checked out several folders below $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

Each folder under src/github.com/jmcvetta/ is the root of a separate git checkout.

That attracted some criticisms though, in this reddit page:

I highly recommend not structuring the repo the way you have, it'll break "go get", which is one of the most useful things about Go.
It's far better to write your code for people who do know Go, since they're most likely to be the ones compiling it.
And for people who don't, they'll at least get a feel for the language.

Put the main package in the root of the repo.
Have the assets in a subdirectory (to keep things neat).
Keep the meat of the code in a subpackage (in case anyone wants to reuse it outside your binary).
Include a setup script in the root of the repo so it's easy to find.

It's still only a two step process to download, build, install, and setup.:

  • "go get <your repo path>": downloads and installs the go code, with a subdir for the assets
  • $GOPATH/<your repo path>/setup.sh: distributes the assets to the right place and installs the service

这篇关于什么是布局Go项目的明智方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆