如何优雅的组织Golang项目结构
创始人
2025-07-08 03:31:25
0

一个Go项目的结构设计始终遵循Go语言的简洁高效理念。一个合理和良好的布局可以提高代码的可读性,简化依赖管理,并优化编译过程。

像cmd、internal和docs这样的目录是标准Go项目的基础,起着不同的作用。比如,cmd目录是可执行文件的入口,docs是所有相关文档的入口,而internal包含项目私有代码。适当的包划分可以避免循环依赖,便于单元测试和代码复用。

然而,这种Go项目布局可能导致过多的目录层级和包划分,会给管理工作带来负担,并有时让初学者感到不知所措。

因此,在设计时如何把握什么算是“合理”,就成了关键。

这篇文章,让我们尝试在目录结构和包设计中找到简洁和功能之间的平衡,使项目能够在变化中健康迭代。

标准布局

像cmd和internal这样的目录结构是由一些Go语言社区的开发者在系统总结之前进行了总结,并在标准Go项目布局中得到了进一步的概括,该项目已经获得了超过4万个star。尽管其起源是一个提示,但标准布局已经成为Go项目目录结构的事实标准。

这并不是由核心Go开发团队定义的官方标准。

my-app/ # Root directory of the project
|── cmd/ # Executables directory
└── myapp/ # Main application package
└── main.go # Main application entry point
|── internal/ # Private application and library code
└── package1/ # Internal package 1
|── pkg/ # Library code that can be exported
└── package2/ # External package 2
|── api/ # API protocol definitions directory
|── configs/ # Configuration files directory
|── deployments/ # Deployment configurations and scripts
|── scripts/ # Scripts for build, install, analysis, etc.
|── build/ # Packaging and Continuous Integration
|── tests/ # Additional external test apps and test data
|── docs/ # Design and user documents
|── tools/ # Supporting tools for the project
|── examples/ # Application or public library examples
|── third_party/ # External helper tools, forked code, and other 3rd party utilities
|── githooks/ # Git hooks
|── assets/ # Other assets like images, logos, etc.
|── vendor/ # Dependency package directory (if using vendor mode)
|── go.mod # Module dependency file
|── go.sum # Module checksum file for dependency verification

如果你经常阅读源代码,你会轻易地发现,大多数在GitHub上知名的Go开源项目基本上都遵循上述布局,比如Kubernetes这个大型Go项目。

图片图片

让我们简单看一下。

  • 与Go模块相关的go.mod和go.sum是必不可少的。
  • pkg目录包含api、apis、kubectl等包,可应用于外部项目,比如基于Kubernetes的开发。
  • cmd包含了Kubernetes中各种命令行的main方法入口,比如kubectl.go。
  • api目录存储与openApiv3相关的json文件。
  • test目录包含所有的e2e和集成测试代码,根据不同的包进行了分别存储。
  • third_party存储第三方引用的工具,比如protobuf。
  • vendor用于存储外部依赖,比如k8s.io、etcd等。
  • docs目录目前为空。

当然,Kubernetes项目并不完全遵循标准布局,因为其规模较大。例如,许多Kubernetes脚本存储在build和cluster目录中,而不是scripts目录。还有一些用于特定需求的目录,比如hacks和staging。

官方布局

2023年发布的文章《组织Go模块》揭示了Go团队对布局的不同观点,提供了根据项目复杂性设计目录结构的参考,涵盖了具有少量Go文件、单个cmd命令或简单包的项目,以及具有多个cmds和多个包的项目。

对它们进行总结如下,并将其作为下一节的官方布局。

my-module/                 # Root directory for the module with go.mod
├── go.mod                 # Module's dependency file
├── go.sum                 # The module's checksums for dependency validation
├── cmd/                   # Directory for commands (each subdirectory here is a main package)
│   └── my-app/            # Main application for this module
│       └── main.go        # Main application entry point
├── internal/              # Internal packages meant for use only within this module
│   └── mylib/             # An internal package example
│       └── mylib.go       # The package's specific code
├── api/                   # API protocol definitions, e.g., protocol buffer files
├── web/                   # Web application specific components: static files, server-side templates, SPAs, etc.
├── pkg/                   # Library code that's ok to use by external applications (deprecated by some in the community)
│   └── mypkg/             # An example package that could be imported by other applications
│       └── mypkg.go       # Package code
├── README.md              # Project README file
├── LICENSE                # License file
├── .gitignore             # Specifies intentionally untracked files to ignore
└── ...                    <-- Other directories and files as needed

标准布局与官方布局

这两种布局有一些共同的思想。

  • 模块化。不同的功能会被放入不同的包中,以提高可重用性。
  • 提高可见性。根据功能将不同的包存储在不同的目录中,以提高可读性。

基于这些概念,标准布局中有一个通用的cmd目录来存储命令行代码,子包用于保存多个命令,internal目录用于保存不对外共享的代码。目录路径和包名称与main.go作为入口文件保持一致。

但是,它们对于像pkg和util这样的目录有不同的考虑,例如,Russ Cox反对以pkg和util等模糊方式命名软件库。此外,由于社区的贡献,标准布局比官方建议覆盖范围更广,添加了像scripts和build这样的目录。

Go-Clean-Template

标准布局和官方布局都是通用的,将项目分为cmd项目和非cmd项目,因此对于包含entity和dao等多个包的复杂项目(如使用Go开发的Web项目),它们并不是首选。go-clean-template则专为这类Web项目量身定制。

go-clean-template/       <-- Root directory of the project
├── cmd/                 <-- Main application entry points
│   └── appname/         <-- Specific startup logic and configuration for 'appname' app
│       └── main.go      <-- Main application startup entry
├── internal/            <-- Internal modules, not importable by external applications
│   ├── entity/          <-- Entities (business objects) of the application
│   ├── usecase/         <-- Use case layer containing business logic interfaces
│   ├── repository/      <-- Data storage interfaces
│   ├── handler/         <-- HTTP handlers for receiving requests and calling use cases
│   └── config/          <-- Configuration related code
├── pkg/                 <-- Public library code that can be imported by other projects
├── test/                <-- External testing code
├── .dockerignore        <-- Specifies files to ignore in Docker builds
├── .gitignore           <-- Specifies intentionally untracked files to ignore in Git
├── Dockerfile           <-- Docker configuration file for containerization
├── go.mod               <-- Go module dependencies file
├── go.sum               <-- Checksums for Go module dependencies
└── Makefile             <-- Makefile containing automation commands

作为标准布局的扩展,go-clean-template保留了pkg目录,以便更好地管理众多公共库。它明确定义了像entity、repository、config等子包,省去了我们为它们命名的工作。它还有像test和integration-test这样的目录,用于放置相应的测试代码,提高可读性。

小结

本文带大家深入研究了组织Go代码库的三种布局:

标准布局提供了一个由社区驱动的、广泛适用的结构,非常适合需要清晰关注点分离的大型项目。

官方布局由Go的创建者认可,强调简洁和灵活性,适用于各种项目,特别是那些优先考虑模块管理的项目。

基于Clean Architecture原则的go-clean-template在需要将业务逻辑、数据访问和接口层明确分离以提高可维护性和可测试性的项目中表现出色。

这三种范式适应不同的项目需求,每种都提供了一套可自适应和组合的指南。选择其中之一取决于具体项目的要求、规模和复杂性。

相关内容

热门资讯

如何允许远程连接到MySQL数... [[277004]]【51CTO.com快译】默认情况下,MySQL服务器仅侦听来自localhos...
如何利用交换机和端口设置来管理... 在网络管理中,总是有些人让管理员头疼。下面我们就将介绍一下一个网管员利用交换机以及端口设置等来进行D...
施耐德电气数据中心整体解决方案... 近日,全球能效管理专家施耐德电气正式启动大型体验活动“能效中国行——2012卡车巡展”,作为该活动的...
20个非常棒的扁平设计免费资源 Apple设备的平面图标PSD免费平板UI 平板UI套件24平图标Freen平板UI套件PSD径向平...
德国电信门户网站可实时显示全球... 德国电信周三推出一个门户网站,直观地实时提供其安装在全球各地的传感器网络检测到的网络攻击状况。该网站...
为啥国人偏爱 Mybatis,... 关于 SQL 和 ORM 的争论,永远都不会终止,我也一直在思考这个问题。昨天又跟群里的小伙伴进行...
《非诚勿扰》红人闫凤娇被曝厕所... 【51CTO.com 综合消息360安全专家提醒说,“闫凤娇”、“非诚勿扰”已经被黑客盯上成为了“木...
2012年第四季度互联网状况报... [[71653]]  北京时间4月25日消息,据国外媒体报道,全球知名的云平台公司Akamai Te...