
基于 project-layout 的 Go 标准项目布局目录规范、适用场景与源码级实践指南【免费下载链接】project-layoutStandard Go Project Layout项目地址: https://gitcode.com/GitHub_Trending/pr/project-layout本文以本仓库的意大利语文档 README_it.md 为主体系统讲解 Go 社区通用的标准项目布局Standard Go Project Layout每个核心目录cmd、internal、pkg、api、web、configs、scripts、deployments等的职责、命名规则与取舍依据。读完之后你将能够为自己的 Go 应用挑选合适的目录骨架、理解internal包的编译器级强制机制并基于本仓库模板快速搭建一个结构清晰的 Go 项目。一、这套布局的定位社区模式集合而非官方标准文档开宗明义地强调这套布局并不是 Go 核心团队定义的官方标准。它是 Go 生态中长期沉淀下来的一组常见历史与新兴项目布局模式其中一些模式比其他模式更流行同时它也附带了一些小改进以及几乎所有足够大的真实世界应用都会用到的若干支撑目录。文档还给出三个关键定位刻意保持通用性这套结构不试图强加某种特定的 Go 包结构例如 Clean Architecture 之类的分层方式就不在此讨论范围内社区协作成果如果你发现新的模式或者认为某个现有模式需要更新应当通过 issue 提出按需裁剪目录存在不代表必须使用——连vendor模式也不是万能的。什么时候该用、什么时候不该用文档用加粗语气给出了一条最重要的建议如果你正在学习 Go或者只是在开发 PoC概念验证或个人简单项目这套布局是不必要的复杂化。请从真正简单的结构开始——一个main.go文件和go.mod就足够了。随着项目演进布局的重要性分阶段上升项目增长期要时刻保证代码结构良好否则会演变成一堆隐藏依赖 全局状态的混乱代码多人协作期需要更有结构的布局并引入管理包/库的通用方式开源或被依赖期当你的仓库是开源项目、或有其他项目会 import 你的代码时就必须明确私有包与代码即internal目录的边界。文档给出的落地建议是克隆本仓库保留你需要的部分删除其余一切。克隆命令如下这是全文唯一涉及仓库地址的场景git clone https://gitcode.com/GitHub_Trending/pr/project-layoutGo Modules 前提从 Go 1.14 起不再被 $GOPATH 束缚从 Go 1.14 开始Go Modules 正式达到生产可用。文档建议除非你有特定理由不用否则一律使用 Go Modules——这样你就不必再操心$GOPATH和项目放置位置的问题。关于模块路径module path有一条容易被忽视的细节仓库自带的 go.mod 文件内容非常简洁// go.mod (仓库根目录) module github.com/YOUR-USER-OR-ORG-NAME/YOUR-REPO-NAME go 1.19文档说明这份go.mod默认假设你的项目托管在 GitHub 上但这并非强制要求——模块路径可以是任意值不过模块路径的第一段应当包含一个点域名形式。当前版本的 Go 已不再强制这一点但如果你使用稍旧版本的 Go构建失败时不妨先怀疑这里文档同时引用了 golang/go 的 issue #37554 与 #32819 供进一步阅读见官方仓库。命名、格式与风格先跑工具再读指南文档建议遇到命名、格式、风格问题时先从运行gofmt开始。需要说明的是意大利语文档中提到的标准 linter 是golint而仓库中最新的英文主文档 README.md 已更新为推荐staticcheck——因为 golint 现已弃停维护若以当前仓库状态为准优先使用 staticcheck 这类仍在维护的 linter。此外文档列出了一批必读的命名与风格指南此处仅保留条目名称不再附外部链接Go Naming Conventions 演讲talks.golang.org2014Effective Go 的 Naming 章节《Package names in Go》官方博客CodeReviewComments wikirakyll/JBD 的《Go 包风格指南》Package-Oriented Style以及关于包命名、包组织与代码结构建议的四场经典演讲GopherCon EU 2018 Peter Bourgon 的工业级编程最佳实践、GopherCon Russia 2018 的 Go best practices、GopherCon 2017 Edward Muller 的 Go 反模式、GopherCon 2018 Kat Zien 的 Go 应用结构和一篇关于面向包的设计与架构分层的中文文章。二、Go 目录cmd、internal、pkg、vendor这是文档中权重最高的四个 Go 专属目录也是整套布局的核心骨架。/cmd本项目的主应用程序/cmd存放本项目的主应用可执行程序。规则有四点每个应用的目录名应与期望的可执行文件名一致例如/cmd/myapp不要在应用目录里堆大量代码如果代码可能被其他项目 import 复用就放进/pkg如果不可复用、或你明确不希望别人复用就放进/internal——你无法预测别人会怎么 import 你的代码所以要把意图表达得足够显式最常见、也最推荐的做法是写一个很小的main函数只做 import 并调用/internal与/pkg中的代码别无其他子目录说明文档 cmd/README.md 列出了采用该模式的主流项目包括 velero、moby、prometheus、influxdb、kubernetes、dapr、go-ethereum 等。本仓库中cmd/_your_app_/就是一个空占位目录提示你按可执行文件名创建子目录。/internal编译器强制的私有代码/internal存放不希望他人 import的私有应用与库代码。文档强调两个机制性事实该模式由 Go 编译器本身强制只要包位于internal目录下其他包就无法 import 它除非共享公共祖先路径。这是自 Go 1.4 起的行为见 Go 1.4 发布说明中的 internal packages 一节internal不限于顶层你可以在项目树的任意层级放置多个internal目录。文档还推荐了一个可选的二级结构用于区分共享的内部代码与非共享的内部代码小项目不必做但能提供更清晰的包用途暗示实际应用代码放在/internal/app例如/internal/app/myapp这些应用共享的内部代码放在/internal/pkg例如/internal/pkg/myprivlib。这一推荐结构在本仓库中被真实落地为占位目录internal/ ├── app/ │ └── _your_app_/ # 应用私有代码不共享 └── pkg/ └── _your_private_lib_/ # 应用间共享的私有库子目录文档 internal/README.md 进一步列出了使用internal的知名项目hashicorp/terraform、influxdb、perkeep、jaeger、moby、minio 等其中 hashicorp/waypoint 展示了/internal/pkg的用法。/pkg明确可供外部使用的公开库/pkg存放允许外部应用使用的库代码例如/pkg/mypubliclib。文档对此目录的态度可以概括为三层谨慎放入其他项目会 import 这些库并默认它们能正常工作因此放任何东西进去之前要想清楚internal才是硬保证真正从机制上阻止 import 的是internal目录Go 编译器强制而/pkg的价值在于**显式地对外传达这里的代码可以被安全使用**这一契约。社区作者 Travis Jeffery 的博文《Ill take pkg over internal》对pkg与internal的取舍给出了很好的综述见子目录文档 pkg/README.md 的引用它也是工程组织手段当项目根目录混杂大量非 Go 组件时把 Go 代码统一收拢到/pkg下可以让各种 Go 工具更好用——这一点在 GopherCon EU 2018Peter Bourgon、GopherCon 2018Kat Zien与 GoLab 2018Massimiliano Pippi三场演讲中均有论述。文档同时坦诚了社区争议pkg是一个常见但并非普遍接受的模式Go 社区中有人并不推荐它如果你的项目很小、多一层嵌套没有价值完全可以不用。pkg/README.md 附有一长串使用pkg布局的知名仓库清单containerd、istio、helm、k3s、kubernetes、moby、grafana、cockroach、etcd、linkerd、spire 等可作为采用与否的参考样本。最后文档交代了pkg目录的历史起源早期 Go 官方源码树曾用pkg目录存放其包社区项目随之模仿了这一模式Brad Fitzpatrick 的相关推文提供了更多背景。/vendor应用依赖/vendor存放应用依赖——可以手工管理也可以用你偏好的依赖管理工具比如内置的 Go Modules执行go mod vendor命令即可自动生成/vendor目录注意如果你没有使用 Go 1.14该版本起默认启用 vendor 模式可能需要在go build命令上追加-modvendor标志构建库时不要提交你的应用依赖自 Go 1.13 起Go 启用了 module proxy 特性默认使用官方代理服务器 proxy.golang.org。如果你的需求与约束能被它满足就完全不需要vendor目录。本仓库当前并未包含vendor目录与依赖交给模块代理/go mod vendor生成的定位一致。三、服务应用目录/api/api存放 OpenAPI/Swagger 规范、JSON schema 文件与协议定义文件。这是一个面向服务化应用的目录接口契约与实现代码分离便于生成客户端或文档。子目录文档 api/README.md 给出的参考项目是 kubernetes 与 moby 的api目录。四、Web 应用目录/web/web存放 Web 应用专属组件静态 Web 资源、服务端模板与 SPA单页应用。从本仓库的实际结构看该目录已被细分为三个占位子目录给出了推荐的组织方式web/ ├── app/ # 前端应用如 SPA 源码 ├── static/ # 静态资源 └── template/ # 服务端模板对应的目录说明见 web/README.md。五、通用应用目录configs、init、scripts、build、deployments、test/configs配置模板与默认配置存放配置文件模板或默认配置例如confd或consul-template的模板文件也应放在这里。说明见 configs/README.md。/init系统初始化与进程管理存放系统初始化systemd、upstart、sysv与进程管理器/守护器runit、supervisord的配置。说明见 init/README.md。/scripts构建与运维脚本存放执行各类构建、安装、分析等操作的脚本。文档指出这类脚本的核心作用是让根级 Makefile 保持小巧、直接以 hashicorp/terraform 的 Makefile 为范例。这一点在本仓库中被贯彻到了极致——仓库根目录的 Makefile 全文只有一行注释# note: call scripts from /scripts即所有实际逻辑都被推给了/scripts下的脚本根 Makefile 仅作为入口提示。这正示范了文档所说的根 Makefile 小而简单原则。更多示例见 scripts/README.md。/build打包与持续集成/build承担打包Packaging与 CI 两类职责文档建议拆成两个子目录/build/package放置云镜像AMI、容器Docker、操作系统包deb、rpm、pkg的打包配置与脚本/build/ci放置 CItravis、circle、drone的配置与脚本。文档特别提醒某些 CI 工具如 Travis CI对配置文件位置要求非常严格可以把配置放在/build/ci下再通过链接link指到 CI 工具期望的路径在可行的情况下。/deployments部署配置与模板存放 IaaS、PaaS、系统级以及容器编排的部署配置与模板docker-compose、kubernetes/helm、mesos、terraform、bosh 等。文档注意到一个命名差异在部分仓库中尤其是用 kubernetes 部署的应用这个目录叫/deploy。本仓库采用了deployments/命名说明见 deployments/README.md。/test外部测试应用与测试数据/test存放额外的外部测试应用与测试数据内部结构可自由组织。文档给出两条与 Go 工具链直接相关的实用规则大型项目建议设一个数据子目录如/test/data若需要 Go 工具链忽略目录内容应命名为/test/testdataGo 的构建/测试工具会自动跳过testdata目录由于Go 同样会忽略以.或_开头的目录和文件测试数据目录的命名还有更大自由度——这也解释了本仓库为何大量使用_your_app_、_your_private_lib_这类下划线前缀占位目录它们既是模板占位符又天然被 Go 工具忽略。示例见 test/README.md。六、其他目录docs、tools、examples、third_party、githooks、assets、website目录职责补充说明/docs用户文档与设计文档补充在自动生成的 godoc 文档之外docs/README.md/tools项目的支撑工具注意这些工具可以 import/pkg与/internal中的代码tools/README.md/examples应用与/或公开库的使用示例examples/README.md/third_party外部辅助工具、fork 的代码、其他第三方工具如 Swagger UIthird_party/README.md/githooksGit hooksgithooks/README.md/assets仓库附带的其他资源图片、logo 等assets/README.md/website如果不使用 GitHub pages项目网站数据放在这里website/README.md值得注意的是/tools的 import 规则工具既依赖项目代码可 importpkg/internal又不应被主程序反向依赖——这为脚手架/代码生成器/内部 CLI类工具划定了一个安全的存放位置。七、不该出现的目录/src文档专设一节警告不要在 Go 项目中使用/src目录。理由分两层来源判断Go 项目出现src目录通常是因为开发者来自 Java 世界Java 中src是常见模式。文档直接建议尽量别把 Go 项目做得像 Java 项目避免与 Go workspace 的/src混淆$GOPATH环境变量指向当前的工作区非 Windows 系统上默认是$HOME/go该工作区包含顶层的/pkg、/bin与/src三个目录你的实际项目会落在工作区的/src之下。如果项目自身再嵌套一个/src路径就会变成/some/path/to/workspace/src/your_project/src/your_code.go这种双层src。文档最后补充虽然自 Go 1.11 起项目可以放在GOPATH之外但这并不意味着/src布局就是好主意。八、仓库骨架总览一个可裁剪的纯模板结合上文对文档各目录的解读再看本仓库的实际骨架可以完整对照出这套布局的全貌仓库内不含任何.go源码文件是一个纯目录模板配合 LICENSE.md 与上文所示的 go.mod、Makefile. ├── api/ # OpenAPI/Swagger/JSON schema/协议定义 ├── assets/ # 图片、logo 等仓库资源 ├── cmd/ │ └── _your_app_/ # 主应用目录名可执行文件名 ├── configs/ # 配置模板/默认配置含 confd、consul-template ├── deployments/ # IaaS/PaaS/编排部署docker-compose、k8s/helm、terraform… ├── docs/ # 用户与设计文档 ├── examples/ # 应用/公开库示例 ├── githooks/ # Git hooks ├── init/ # systemd/upstart/sysv、runit、supervisord ├── internal/ │ ├── app/_your_app_/ # 应用私有代码 │ └── pkg/_your_private_lib_/ # 应用间共享私有库 ├── pkg/ │ └── _your_public_lib_/ # 可供外部 import 的公开库 ├── scripts/ # 构建/安装/分析脚本根 Makefile 保持精简 ├── test/ # 外部测试应用与测试数据testdata 可被 Go 忽略 ├── third_party/ # 外部工具、fork 代码 ├── tools/ # 支撑工具可 import pkg 与 internal ├── web/ │ ├── app/ # SPA/前端应用 │ ├── static/ # 静态资源 │ └── template/ # 服务端模板 ├── website/ # 项目网站数据非 GitHub pages 时 ├── go.mod # module 路径为占位符需替换为你自己的 ├── Makefile # 仅一行call scripts from /scripts └── LICENSE.md使用流程与文档的结论一致克隆仓库 → 保留所需目录、删除其余 → 替换 go.mod 中的模块路径占位符github.com/YOUR-USER-OR-ORG-NAME/YOUR-REPO-NAME→ 把cmd、internal、pkg下带下划线前缀的占位目录重命名为真实名称。下划线前缀目录同时享受 Go 工具链自动忽略的便利。九、Badges仓库文档面板文档最后给出了 README badge 的推荐用法此处按当前仓库内容说明用途不附外链Go Report Card会用gofmt、go vet、gocyclo、golint、ineffassign、license、misspell扫描你的代码把示例中的模块引用替换为你的项目即可Pkg.go.devGo 包发现与文档的新入口可用其 badge 生成工具为项目创建 badgeRelease badge展示项目的最新 release 版本号把链接指向你的项目即可。十、小结这套布局的完整心法可以压缩为三句话cmd薄、internal硬、pkg慎——可执行入口保持极小私有性交给编译器强制的internal公开 API 才进pkg并视为对外承诺非 Go 组件各归其位——api、web、configs、init、deployments、scripts、test、docs、website等目录让根目录始终可读按需裁剪——学习期只用main.gogo.mod项目长大、多人协作、对外发布三个阶段逐级加结构目录在模板中存在不等于你必须使用它。文档末尾的 Notes 还提到一个包含简单可复用配置、脚本与代码的更有主见的标准项目模板仍在进行中WIP可作为后续关注方向。【免费下载链接】project-layoutStandard Go Project Layout项目地址: https://gitcode.com/GitHub_Trending/pr/project-layout创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考