组织一个多文件的Go项目

huangapple go评论62阅读模式
英文:

Organizing a multiple-file Go project

问题

这个问题与这个问题有关,但是两年的时间在Go的历史中是非常长的。

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

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

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

我应该如何组织这个?每次想要尝试它时,我需要执行go install mypack吗?

英文:

Note: this question is related to this one, but two years is a very long time in Go history.

What is the standard way to organize a Go project during development ?

My project is a single package mypack, so I guess I put all the .go files in a mypack directory.

But then, I would like to test it during development so I need at least a file declaring the main package, so that I can do go run trypack.go

How should I organize this ? Do I need to do go install mypack each time I want to try it ?

答案1

得分: 176

我建议您查看如何编写Go代码页面。

它介绍了如何以go build友好的方式组织项目结构,以及如何编写测试。测试不需要使用main包来创建一个命令行程序。它们可以简单地作为每个包中以TestX命名的函数的一部分,然后go test会自动发现它们。

在您提问中提到的链接中建议的项目结构已经有些过时了,现在Go 1已经发布。您不再需要在src下放置一个pkg目录。与规范相关的三个目录只需要在您的GOPATH的根目录下: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的概念即将过时。

英文:

I would recommend reviewing this page on How to Write Go Code

It documents both how to structure your project in a go build friendly way, and also how to write tests. Tests do not need to be a cmd using the main package. They can simply be TestX named functions as part of each package, and then go test will discover them.

The structure suggested in that link in your question is a bit outdated, now with the release of Go 1. You no longer would need to place a pkg directory under src. The only 3 spec-related directories are the 3 in the root of your GOPATH: bin, pkg, src . Underneath src, you can simply place your project mypack, and underneath that is all of your .go files including the mypack_test.go

go build will then build into the root level pkg and bin.

So your GOPATH might look like this:

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

export GOPATH=$HOME/projects

$ go build mypack
$ go test mypack

Update: as of >= Go 1.11, the Module system is now a standard part of the tooling and the GOPATH concept is close to becoming obsolete.

答案2

得分: 61

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

英文:

jdi has the right information concerning the use of GOPATH. I would add that if you intend to have a binary as well you might want to add one additional level to the directories.

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

running go build myproj/mypack will build the mypack package along with it's dependencies
running go build myproj/myapp will build the myapp binary along with it's dependencies which probably includes the mypack library.

答案3

得分: 51

我研究了许多Go项目,发现它们之间有很大的差异。你可以从中看出是来自C还是来自Java的开发者,前者几乎将所有内容都放在项目的根目录下的main包中,而后者则倾向于将所有内容放在src目录中。然而,这两种方式都不是最佳选择。它们都会产生后果,因为它们会影响导入路径以及其他人如何重用它们。

为了获得最佳结果,我总结了以下方法。

myproj/
  main/
    mypack.go
  mypack.go

其中,mypack.gopackage mypackmain/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

英文:

I have studied a number of Go projects and there is a fair bit of variation. You can kind of tell who is coming from C and who is coming from Java, as the former dump just about everything in the projects root directory in a main package, and the latter tend to put everything in a src directory. Neither is optimal however. Each have consequences because they affect import paths and how others can reuse them.

To get the best results I have worked out the following approach.

myproj/
  main/
    mypack.go
  mypack.go

Where mypack.go is package mypack and main/mypack.go is (obviously) package main.

If you need additional support files you have two choices. Either keep them all in the root directory, or put private support files in a lib subdirectory. E.g.

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

Or

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

Only put the files in a lib directory if they are not intended to be imported by another project. In other words, if they are private support files. That's the idea behind having lib --to separate public from private interfaces.

Doing things this way will give you a nice import path, myproj.org/mypack to reuse the code in other projects. If you use lib then internal support files will have an import path that is indicative of that, myproj.org/lib/mysupport.

When building the project, use main/mypack, e.g. go build main/mypack. If you have more than one executable you can also separate those under main without having to create separate projects. e.g. main/myfoo/myfoo.go and main/mybar/mybar.go.

答案4

得分: 21

我发现理解如何在Golang中组织代码非常有用,这是Caleb Doxsey写的书中的第11章。

英文:

I find very useful to understand how to organize code in Golang this chapter http://www.golang-book.com/11 of the book written by Caleb Doxsey

答案5

得分: 14

似乎没有一种标准的方法来组织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/

英文:

There doesn't seem to be a standard way of organizing Go projects but https://golang.org/doc/code.html specifies a best practice for most projects. jdi's answer is good but if you use github or bitbucket and you have additional libraries as well, you should create the following structure:

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

By doing it this way, you can have a separate repository for mylib that can be used for other projects and can be retrieved by "go get". Your mypack project can import your library using "github.com/username/mylib". For more information:

http://www.alexvictorchan.com/2014/11/06/go-project-structure/

答案6

得分: 7

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

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

然后运行:

~/myproj/your-program$ go build && ./your-program
英文:

Keep the files in the same directory and use package main in all files.

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

Then run:

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

答案7

得分: 7

让我们来探索一下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项目可以分为以下几类:

  • (没有可执行二进制文件)
  • 单一项目(只包含一个可执行二进制文件)
  • 工具项目(包含多个可执行二进制文件)

通常,golang项目文件可以按照任何设计原则进行打包,例如DDDPOD。大多数可用的go项目都遵循这种Package Oriented Design

Package Oriented Design鼓励开发人员将实现仅保留在自己的包中,除了/internal包,这些包不能相互通信。


  • 诸如数据库驱动qt之类的项目可以归类为此类别。
  • 一些库,如colornow,采用了平坦的结构,没有其他包。
  • 大多数这些库项目管理一个名为internal的包。
  • /internal包主要用于隐藏实现细节,防止其他项目访问。
  • 没有可执行二进制文件,因此没有包含main func的文件。

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

单一项目

  • 诸如hugoetcd之类的项目在根级别有一个单一的main func。
  • 目标是生成一个单一的二进制文件。

工具项目

  • 诸如kubernetesgo-ethereum之类的项目在一个名为cmd的包下组织了多个main func。
  • 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/
英文:

Let's explorer how the go get repository_remote_url command manages the project structure under $GOPATH. If we do a go get github.com/gohugoio/hugo It will clone the repository under

> $GOPATH/src/repository_remote/user_name/project_name


> $GOPATH/src/github.com/gohugoio/hugo

This is a nice way to create your initial project path. Now let's explorer what are the project types out there and how their inner structures are organized. All golang projects in the community can be categorized under

  • Libraries (no executable binaries)
  • Single Project (contains only 1 executable binary)
  • Tooling Projects (contains multiple executable binaries)

Generally golang project files can be packaged under any design principles such as DDD, POD

Most of the available go projects follows this Package Oriented Design

Package Oriented Design encourage the developer to keeps the implementation only inside it's own packages, other than the /internal package those packages can't can communicate with each other


Libraries

  • Projects such as database drivers, qt can put under this category.
  • Some libraries such as color, now follows a flat structure without any other packages.
  • Most of these library projects manages a package called internal.
  • /internal package is mainly used to hide the implementation from other projects.
  • Don't have any executable binaries, so no files that contains the main func.

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

Single Project

  • Projects such as hugo, etcd has a single main func in root level and.
  • Target is to generate one single binary

Tooling Projects

  • Projects such as kubernetes, go-ethereum has multiple main func organized under a package called cmd
  • cmd/ package manages the number of binaries (tools) that we want to build

 ~/$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/

huangapple
  • 本文由 发表于 2012年4月3日 08:20:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/9985559.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定