Golang项目目录结构

goo*_*lei 12 go gopath

关于Golang目录结构,我有些困惑.

根据名为<The way to go>的书,项目代码应放入src,并推荐以下目录结构.

    ???src/
    |  ???main.go
    |  ???say/
    |  |  ???say.go
    |  |  ???say_test.go
    ???bin/
    |  ???say
    ???pkg/
       ???linux_amd64/
          ???say.a
Run Code Online (Sandbox Code Playgroud)

但我发现很多包里面github.com都没有src目录.

例如:

https://github.com/facebookgo/grace

https://github.com/astaxie/beego

所以,我不知道是否src需要目录.

我有一些项目,他们有相互依赖.它们在私有GitLab存储库中管理.

我怎么组织他们?

Ste*_*rer 11

当我开始使用Go时,Ben Johnson的这篇文章引导了我.

从这样的事情开始通常是好的(假设你在项目目录中,如$GOPATH/src/myproject:

???cmd/ -- this is where you compose several packages in to main package
|  ???foo -- an example would be `foo`
|  |  ???main.go
???pkg/ -- this is where put your reusable packages 
|  ???pkg1 -- reusable package 1
|  ???pkg2 -- reusable package 2
???otherpackage1
|  ??? ...
???otherpackage2
|  ??? ...
Run Code Online (Sandbox Code Playgroud)

对于这种项目结构,您可以查看示例go-kit.

有时它取决于您的需求.在我们的工作流程中,我们使用名为fresh的热代码重新加载工具,因此我们需要将main.go项目置于根目录上,以便该工具可以检测所有文件更改并重建源代码.

???app/
|  ???app.go
???model/ -- 
|  ???model.go
???store
|  ???store.go
???main.go -- this is where the app starts
???...
Run Code Online (Sandbox Code Playgroud)

app.go包上,我有类似的东西func Run() error启动应用程序.在main.go,我只是调用函数:

...
func main(){
    log.Fatal(app.Run())
}
Run Code Online (Sandbox Code Playgroud)


zan*_*ngw 10

更新于 2023 年 11 月 23 日

\n

go.dev 上《组织 Go 模块》的摘要

\n
\n

刚接触 Go 的开发人员的一个常见问题是 \xe2\x80\x9c 如何组织我的 Go 项目?\xe2\x80\x9d,就文件和文件夹的布局而言。本文档的目的是提供一些指南来帮助回答这个问题。

\n
\n
    \n
  • 基本包\n
      \n
    • 一个基本的Go包的所有代码都在project\xe2\x80\x99s根目录中。该项目由单个模块组成,该模块又由单个包组成。包名称与模块名称的最后一个路径部分匹配。对于需要单个 Go 文件的非常简单的包,项目结构为:
    • \n
    \n
  • \n
\n
project-root-directory/\n  go.mod\n  modname.go\n  modname_test.go\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 基本命令\n
      \n
    • 基本可执行程序(或命令行工具)是根据其复杂性和代码大小构建的。最简单的程序可以由定义的单个 Go 文件组成func main。较大的程序可以将其代码拆分为多个文件,所有文件都声明package main
    • \n
    \n
  • \n
\n
project-root-directory/\n  go.mod\n  auth.go\n  auth_test.go\n  client.go\n  main.go\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 带有支持包的包或命令\n
      \n
    • 较大的包或命令可能会受益于将某些功能拆分为支持包。最初,它\xe2\x80\x99s建议将此类包放入名为internal的目录中;这可以防止其他模块依赖于我们不一定想要公开和支持外部使用的包。
    • \n
    \n
  • \n
\n
project-root-directory/\n  internal/\n    auth/\n      auth.go\n      auth_test.go\n    hash/\n      hash.go\n      hash_test.go\n  go.mod\n  modname.go\n  modname_test.go\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 多个包\n
      \n
    • 一个模块可以由多个可导入包组成;每个包都有自己的目录,并且可以分层结构。
    • \n
    \n
  • \n
\n
project-root-directory/\n  go.mod\n  modname.go\n  modname_test.go\n  auth/\n    auth.go\n    auth_test.go\n    token/\n      token.go\n      token_test.go\n  hash/\n    hash.go\n  internal/\n    trace/\n      trace.go\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 多个命令\n
      \n
    • 同一存储库中的多个程序通常具有单独的目录
    • \n
    \n
  • \n
\n
project-root-directory/\n  go.mod\n  internal/\n    ... shared internal packages\n  prog1/\n    main.go\n  prog2/\n    main.go\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 包和命令位于同一存储库中\n
      \n
    • 有时,存储库会提供可导入的包和具有相关功能的可安装命令。
    • \n
    \n
  • \n
\n
project-root-directory/\n  go.mod\n  modname.go\n  modname_test.go\n  auth/\n    auth.go\n    auth_test.go\n  internal/\n    ... internal packages\n  cmd/\n    prog1/\n      main.go\n    prog2/\n      main.go\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 服务器项目\n
      \n
    • 服务器项目通常不会\xe2\x80\x99 具有用于导出的包,因为服务器通常是独立的二进制文件(或一组二进制文件)。因此,\xe2\x80\x99s 建议将实现 server\xe2\x80\x99s 逻辑的 Go 包保留在内部目录中。此外,由于该项目可能有许多其他包含非 Go 文件的目录,因此将所有 Go 命令放在一个 cmd 目录中是一个好主意
    • \n
    \n
  • \n
\n
project-root-directory/\n  go.mod\n  internal/\n    auth/\n      ...\n    metrics/\n      ...\n    model/\n      ...\n  cmd/\n    api-server/\n      main.go\n    metrics-analyzer/\n      main.go\n    ...\n  ... the project\'s other directories with non-Go code\n
Run Code Online (Sandbox Code Playgroud)\n
\n

这是另一个项目布局示例带有模块的简单 Go 项目布局

\n
\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 LICENSE\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 README.md\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 config.go\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 go.mod\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 go.sum\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 clientlib\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 lib.go\n\xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 lib_test.go\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 cmd\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 modlib-client\n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main.go\n\xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 modlib-server\n\xe2\x94\x82       \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main.go\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 internal\n\xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 auth\n\xe2\x94\x82       \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 auth.go\n\xe2\x94\x82       \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 auth_test.go\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 serverlib\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 lib.go\n
Run Code Online (Sandbox Code Playgroud)\n

一些答案指出了go 标准布局,但是,有一个问题,这不是标准的 Go 项目布局Russ Cox 的标准 Go 项目布局

\n
\n

这个 GitHub 存储库有两个问题:

\n
\n
\n
    \n
  • 它声称拥有 Go 标准,但实际上并没有,因为这些绝不是官方标准
  • \n
  • 它提出的项目布局标准过于复杂,不是一个标准
  • \n
\n
\n
\n

关于“为什么不告诉我们标准的 Go 项目布局,我们将更新文档?”,这只解决了第 2 点。如果有标准,标准将位于主 Go 项目文档树中。项目布局的标准也会短得多。我很感激您尝试提供有用的资源,但称其为“golang-standards”是夸大其词。

\n
\n
\n

但郑重声明,可导入 Go 存储库的最小标准布局实际上是:

\n
\n
\n
    \n
  • 将 LICENSE 文件放入您的根目录中
  • \n
  • 将 go.mod 文件放入根目录中
  • \n
  • 将 Go 代码放入您的存储库、根目录中或按照您认为合适的方式组织到目录树中
  • \n
\n
\n
\n

就是这样。这就是“标准”。

\n
\n
\n

更新于 11/30/2021

\n

这是来自的摘要这是《如何构建 Go 代码》

\n
    \n
  • 在我们开始之前\n
      \n
    • doc.go文件放置了包的一般描述
    • \n
    • Readme提交该项目的总体概述
    • \n
    • 当您有更多文档需要提供时,请将它们放入docs文件夹中
    • \n
    • 对于 linting,请使用 golangci-lint。启用所有看起来对您的项目合理的 linter
    • \n
    \n
  • \n
  • 扁平结构(单封装)\n
    courses/\n  main.go\n  server.go\n  user_profile.go\n  lesson.go\n  course.go\n
    Run Code Online (Sandbox Code Playgroud)\n
      \n
    • 何时创建新包?\n
        \n
      • 当您有多种启动申请的方式时
      • \n
      • 当你想提取更详细的实现时
      • \n
      • 当您开始为密切相关的事物添加通用前缀时
      • \n
      \n
    • \n
    \n
  • \n
  • 模块化\n
      \n
    • 按种类整理
    • \n
    \n
  • \n
\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 handlers\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 course.go\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 lecture.go\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 profile.go\n\xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 user.go\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 main.go\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 models\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 course.go\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 lecture.go\n\xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 user.go\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 repositories\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 course.go\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 lecture.go\n\xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 user.go\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 services\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 course.go\n\xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 user.go\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 utils\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 stings.go\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 按组件组织
  • \n
\n
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 course\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 httphandler.go\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 model.go\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 repository.go\n\xe2\x94\x82   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 service.go\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 main.go\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 profile\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 httphandler.go\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 model.go\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 repository.go\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 service.go\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  • 简洁的架构\n
      \n
    • 您的应用程序或模块有 4 层(取决于您的代码库有多大):域、应用程序、端口、适配器。在某些来源中,名称可能有所不同。
    • \n
    \n
  • \n
\n


Rad*_*ina 7

现在有组织 golang 项目的新方法。进入golang-standards的 github ,有说:

这是 Go 应用程序项目的基本布局。它代表了最常见的目录结构,具有许多小的增强功能以​​及任何现实世界应用程序共有的几个支持目录。

这个项目布局是故意通用的,它不会试图强加特定的 Go 包结构。

或者您可以按照此幻灯片进行操作

$GOPATH/
    src/
        github.com/user/repo/
            mypkg/
                mysrc1.go
                mysrc2.go
            cmd/mycmd/
                main.go
    bin/
        mycmd
Run Code Online (Sandbox Code Playgroud)

  • 尽管 repo 包含几个有趣的点,但它似乎_不是_golang 的官方指南。换句话说,这只是关于该主题的“另一种”意见,因此我不会将其定位为“新方式”,因为“新方式”听起来像是推翻现有指导的终极指导。 (4认同)

Fro*_*gon 3

src 目录是不需要的,事实上很多公共存储库不使用这种结构。

\n\n

有几种不同的方式来组织您的项目。如果您计划让其他存储库(例如 lib.lib)使用您的项目。我建议使用类似这样的 cmd 结构。如果启动应用程序的方法不止一种,这也将是推荐的方法。(多个main.go文件)

\n\n
\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80cmd/\n|  \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80(application name)\n|  |  \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80main.go\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80say/\n   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80say.go\n   \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80say_test.go\n
Run Code Online (Sandbox Code Playgroud)\n\n

否则,例如如果它是一个独立的应用程序。您可以将 main.go 放在存储库的根目录中。

\n\n

bin 和 pkg 您可以保留在根目录中并将其添加到 .gitignore 中。(假设你正在使用git)

\n

  • @Compree 你的意思是不同意?有一个名为 [Directories You Shouldn't Have](https://github.com/golang-standards/project-layout#directories-you-shouldnt-have) 的明确部分,其中包括 `/src` (3认同)