组织一个多文件Go项目

时间:2012-04-03 00:20:14

标签: go

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

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

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

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

我该如何组织这个?每次我想尝试时都需要go install mypack吗?

7 个答案:

答案 0 :(得分:164)

我建议您在How to Write Go Code

上查看此页面

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

您问题中该链接中建议的结构有点过时,现在发布Go 1.您不再需要在pkg下放置src目录。只有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开始,Module系统现在是工具的标准部分,GOPATH概念即将过时。

答案 1 :(得分:59)

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库。

答案 2 :(得分:47)

我研究过很多Go项目,并且有很多变化。您可以告诉谁来自C以及谁来自Java,因为前者只是转储main包中项目根目录中的所有内容,而后者倾向于将所有内容放在{{1}中}} 目录。然而,两者都不是最佳的。每个都有后果,因为它们会影响导入路径以及其他人如何重用它们。

为了获得最佳效果,我制定了以下方法。

src

其中myproj/ main/ mypack.go mypack.go mypack.gopackage mypack(显然)为main/mypack.go

如果您需要其他支持文件,您有两种选择。将它们全部保存在根目录中,或将私有支持文件放在package main子目录中。 E.g。

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下的可执行文件分开,而无需创建单独的项目。例如mainmain/myfoo/myfoo.go

答案 3 :(得分:21)

我觉得非常有用了解如何在Golang中组织代码本章http://www.golang-book.com/11由Caleb Doxsey撰写的书

答案 4 :(得分:12)

似乎没有组织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/

答案 5 :(得分:5)

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

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

然后运行:

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

答案 6 :(得分:3)

让我们探索一下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项目文件可以按照任何设计原则打包,例如DDDPOD

大多数可用的go项目都遵循Package Oriented Design

Package Oriented Design鼓励开发人员仅将实现保留在自己的程序包中,而不是那些程序包无法相互通信的/internal程序包


图书馆

  • database driversqt等项目可以归为此类。
  • colornow之类的某些库采用的是扁平结构,没有任何其他软件包。
  • 这些库项目中的大多数都管理一个名为内部的软件包。
  • /internal软件包主要用于对其他项目隐藏实现。
  • 没有任何可执行二进制文件,因此没有包含 main func 的文件。

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

单个项目

  • 诸如hugoetcd之类的项目在根级别上具有单个主功能。
  • 目标是生成一个单一的二进制文件

工具项目

  • kubernetesgo-ethereum之类的项目具有多个主功能,该功能根据名为​​ 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/