Go语言项目布局


Go语言项目布局

参考
Golang项目布局开源项目-29.1K Stars
《Go语言精进之路》第二部分
GopherCon 2018: Kat Zien - How Do You Structure Your Go Apps




1. 前言

在项目中,合理的布局会让项目更加清晰。随着项目的增长,保持良好的项目结构非常重要,否则最终会得到一团混乱的代码。为了便于开发者协作,最好使用通用的结构,下面这个开源项目中介绍了 Go 语言项目布局的最佳实践,目前有接近 3 万个 star,对我后续的开发还是有一定参考价值的。

https://github.com/golang-standards/project-layout

Go 1.14开始,建议Go项目使用Go Modules 进行依赖管理,用 go.mod 来记录特定的依赖信息。




2. Go语言自身结构

作为 Go 语言的创世项目,Go 的项目结构的布局对后续的 Go 语言项目具有重要的参考意义。下面的结构基于 Go 1.16

$ tree -LF 1 /usr/local/go

/usr/local/go
├── AUTHORS
├── CONTRIBUTING.md
├── CONTRIBUTORS
├── LICENSE
├── PATENTS
├── README.md
├── SECURITY.md
├── VERSION
├── api/
├── bin/
├── doc/
├── favicon.ico
├── lib/
├── misc/
├── pkg/
├── robots.txt
├── src/
└── test/

尤其是早期 Go 项目中 src目录下面的结构,更是在后续被 Go 社区作为 Go 应用项目结构的模板广泛使用。

  • 代码构建的脚本源文件放在 src下面的顶层目录下。
  • src下的二级目录 cmd下面存放着 Go 工具链相关的可执行文件(比如 gogofmt等)的主目录以及它们的 main包源文件。
  • src存放着上面 cmd下各工具链程序依赖的包、Go 运行时以及 Go 标准库的源文件。
  • src下面的二级目录 internal,用于存放无法被外部导入、仅 Go 项目自用的包。
  • src下面的 go.modgo.sum,实现了 Go 项目自身的 go module迁移。Go项目内所有包被放到名为 stdmodule下面,其依赖的包依然是 golang.org/x下的各个包。
$ tree -LF 1 /usr/local/go/src

/usr/local/go/src
├── Make.dist
├── README.vendor
├── all.bash*
├── all.bat
├── all.rc*
├── archive/
├── bootstrap.bash*
├── bufio/
├── buildall.bash*
├── builtin/
├── bytes/
├── clean.bash*
├── clean.bat
├── clean.rc*
├── cmd/
├── cmp.bash
├── compress/
├── container/
├── context/
├── crypto/
├── database/
├── debug/
├── embed/
├── encoding/
├── errors/
├── expvar/
├── flag/
├── fmt/
├── go/
├── go.mod
├── go.sum
├── hash/
├── html/
├── image/
├── index/
├── internal/
├── io/
├── log/
├── make.bash*
├── make.bat
├── make.rc*
├── math/
├── mime/
├── net/
├── os/
├── path/
├── plugin/
├── race.bash*
├── race.bat
├── reflect/
├── regexp/
├── run.bash*
├── run.bat
├── run.rc*
├── runtime/
├── sort/
├── strconv/
├── strings/
├── sync/
├── syscall/
├── testdata/
├── testing/
├── text/
├── time/
├── unicode/
├── unsafe/
└── vendor/



3. 以构建二进制可执行文件为目的的 Go 项目结构

下图是一个支持(在 cmd下)构建二进制可执行文件的典型 Go 项目的结构。

项目结构
  • cmd目录:项目的主干,存放项目要构建的可执行文件对应的 main包的源文件。如果有多个可执行文件需要构建,则将每个可执行文件的 main包单独放在一个子目录中,比如图中的 app1、app2。一些Go项目将 cmd这个名字改为 app,但其功能并没有变。
    通常有一个小的 main 函数,从 /internal 和 /pkg 目录导入和调用代码。不要在这个目录中放置太多代码。如果你认为代码可以导入并在其他项目中使用,那么它应该位于 /pkg 目录中。如果代码不是可重用的,或者你不希望其他人重用它,请将该代码放到 /internal 目录中。
  • pkg目录:该目录下的包可以被外部项目引用,算是项目导出包的一个聚合。对于一些规模稍大的项目,过多的包会让项目顶层目录不再简洁,显得很拥挤,因此对于复杂的 Go 项目建议保留 pkg目录。
  • internal目录:对于不想暴露给外部引用,仅限项目内部使用的包,在项目结构上可以通过 Go 1.4 版本中引入的 internal包机制来实现。
  • go.modgo.sum:Go 语言包依赖管理使用的配置文件。
  • Makefile:项目构建工具所用脚本的“代表”,一般会放在 build目录下。



4. 通用应用目录

  • configs目录:配置文件模板或默认配置。
  • init目录:系统初始化文件目录。
  • scripts目录:执行各种构建、安装、分析等操作的脚本。
  • build目录:打包和持续集成。将你的云( AMI )、容器( Docker )、操作系统( deb、rpm、pkg )包配置和脚本放在 /build/package 目录下。将你的 CI (travis、circle、drone)配置和脚本放在 /build/ci 目录中。
  • test目录:额外的外部测试应用程序和测试数据。



5. 其他目录

  • docs目录:设计和用户文档(除了 godoc 生成的文档之外)。
  • tools目录:这个项目的支持工具。注意,这些工具可以从 /pkg 和 /internal 目录导入代码。
  • examples目录:应用程序和/或公共库的示例。
  • third_party目录 :外部辅助工具,分叉代码和其他第三方工具(例如 Swagger UI)。

可以根据项目需求合理添加其他目录结构。

注意:有些 Go 项目确实有一个 src 文件夹,但这通常发生在开发人员有 Java 背景,在那里它是一种常见的模式。如果可以的话,尽量不要采用这种 Java 模式。你真的不希望你的 Go 代码或 Go 项目看起来像 Java




文章作者: xuxiangfei
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 xuxiangfei !
  目录