组织一个多文件Go项目

注意:这个问题与这一个有关,但两年在Go历史上是很长的一段时间。

在开发过程中组织Go项目的标准方法是什么?

我的项目是一个单独的包mypack,所以我想我把所有的.go文件放在一个mypack目录中。

但是,我想在开发过程中测试它,所以我至少需要一个声明main包的文件,这样我就可以做go run trypack.go

我该怎么组织呢?我需要做go install mypack每次我想尝试它吗?

155502 次浏览

我建议您在如何编写Go代码上查看本页

它记录了如何以go build友好的方式构建你的项目,以及如何编写测试。使用main包的测试不需要是cmd。它们可以简单地是TestX命名的函数,作为每个包的一部分,然后go test将发现它们。

你问题中那个链接中建议的结构有点过时了,现在随着Go 1的发布。你不再需要在src下放置一个pkg目录。只有3个与规范相关的目录是GOPATH根目录中的3:bin、pkg、src。在src下面,你可以简单地放置你的项目mypack,下面是你所有的。go文件,包括mypack_test.go

go build将构建到根级别pkg和bin。

所以你的GOPATH可能是这样的:

~/projects/
bin/
pkg/
src/
mypack/
foo.go
bar.go
mypack_test.go

export GOPATH=$HOME/projects

$ go build mypack
$ go test mypack

更新:从>= Go 1.11开始,模块系统现在是工具的标准部分,GOPATH概念接近过时。

jdi有关于GOPATH使用的正确信息。我想补充的是,如果你也想有一个二进制文件,你可能想要在目录中添加一个额外的级别。

~/projects/src/
myproj/
mypack/
lib.go
lib_test.go
...
myapp/
main.go

运行go build myproj/mypack将构建mypack包及其依赖项 运行go build myproj/myapp将构建myapp二进制文件及其依赖项,其中可能包括mypack

保持文件在同一目录下,并在所有文件中使用package main

myproj/
your-program/
main.go
lib.go

然后运行:

~/myproj/your-program$ go build && ./your-program

我研究过许多围棋项目,其中有相当多的变化。你可以看出谁来自C,谁来自Java,因为前者将项目根目录中的所有内容转储到main包中,而后者倾向于将所有内容放在src目录中。然而,这两种方法都不是最佳的。每种方法都会产生后果,因为它们会影响导入路径以及其他人如何重用它们。

为了得到最好的结果,我想出了以下方法。

myproj/
main/
mypack.go
mypack.go

其中mypack.gopackage mypack,而main/mypack.go(显然)是package main

如果你需要额外的支持文件,你有两个选择。要么把它们都放在根目录中,要么把私人支持文件放在lib子目录中。如。

myproj/
main/
mypack.go
myextras/
someextra.go
mypack.go
mysupport.go

myproj.org/
lib/
mysupport.go
myextras/
someextra.go
main/
mypack.go
mypage.go

只有当文件不打算被另一个项目导入时,才将它们放在lib目录中。换句话说,如果它们是私人支持文件。这就是lib——将公共接口与私有接口分开的想法。

这样做会给你一个很好的导入路径myproj.org/mypack,以便在其他项目中重用代码。如果你使用lib,那么内部支持文件将有一个指示的导入路径myproj.org/lib/mysupport

在构建项目时,使用main/mypack,例如go build main/mypack。如果你有多个可执行文件,你也可以在main下分离它们,而不必创建单独的项目。例如:main/myfoo/myfoo.gomain/mybar/mybar.go

我发现非常有用的理解如何组织代码在Golang这一章http://www.golang-book.com/11的书写的Caleb Doxsey

似乎没有组织Go项目的标准方法,但https://golang.org/doc/code.html为大多数项目指定了最佳实践。Jdi的答案很好,但如果你使用github或bitbucket,你也有额外的库,你应该创建以下结构:

~/projects/
bin/
pkg/
src/
github.com/
username/
mypack/
foo.go
bar.go
mypack_test.go
mylib/
utillib.go
utillib_test.go

通过这样做,您可以为mylib拥有一个单独的存储库,可以用于其他项目,并且可以通过“go get”进行检索。你的mypack项目可以使用“github.com/username/mylib”导入你的库。欲了解更多信息:

http://www.alexvictorchan.com/2014/11/06/go-project-structure/ < a href = " http://www.alexvictorchan.com/2014/11/06/go-project-structure/ " > < / >

让我们探索一下go get repository_remote_url命令如何管理$GOPATH下的项目结构。如果我们执行go get github.com/gohugoio/hugo,它将在下面克隆存储库

美元GOPATH / src / repository_remote / user_name / project_name


美元GOPATH / src / github.com/gohugoio/hugo

这是创建初始项目路径的好方法。现在,让我们探索一下有哪些项目类型,以及它们的内部结构是如何组织的。社区中所有的golang项目都可以分为

  • Libraries(没有可执行二进制文件)
  • Single Project(只包含1个可执行二进制文件)
  • Tooling Projects(包含多个可执行二进制文件)

通常,golang项目文件可以打包在任何设计原则下,如DDD圆荚体

大多数可用的go项目都遵循包装导向设计

包装导向设计鼓励开发人员只在自己的包中保持实现,而/internal包除外,这些包不能相互通信


  • 数据库驱动程序qt这样的项目可以放在这个类别下。
  • 一些库,如颜色现在遵循扁平结构,没有任何其他包。
  • 大多数这些库项目管理一个名为内部的包。
  • /internal包主要用于对其他项目隐藏实现。
  • 没有任何可执行二进制文件,因此没有包含主要 函数. xml文件的文件。

 ~/$GOPATH/
bin/
pkg/
src/
repository_remote/
user_name/
project_name/
internal/
other_pkg/

单项目

  • 雨果etcd这样的项目在根级有一个 main func。
  • 目标是生成一个二进制文件

工具项目

  • 诸如kubernetesgo-ethereum等项目的多个 main func被组织在一个名为cmd的包下
  • cmd/包管理我们想要构建的二进制文件(工具)的数量

 ~/$GOPATH/
bin/
pkg/
src/
repository_remote/
user_name/
project_name/
cmd/
binary_one/
main.go
binary_two/
main.go
binary_three/
main.go
other_pkg/