
Go 标准项目布局深度解析基于 project-layout 仓库的目录组织实战指南【免费下载链接】project-layoutStandard Go Project Layout项目地址: https://gitcode.com/GitHub_Trending/pr/project-layout本文基于 project-layout 仓库的法语文档 README_fr.mdStandard Go Project Layout完整展开系统讲解标准 Go 项目布局中cmd、internal、pkg、vendor、api、web等各级目录的定位与取舍原则并结合本仓库真实存在的骨架目录、go.mod、Makefile、.gitignore 与 .editorconfig 逐一印证。读完本文你将能够为 Go 项目搭建一套职责清晰、对编译器语义如internal包强制有明确依据的目录结构并知道哪些模式该保留、哪些应当删掉。一、标准布局的定位与适用边界README_fr.md 的开篇给出了一条必须牢记的定性说明该仓库代表的布局并不是 Go 官方开发团队定义的标准而是从 Go 生态中历史悠久或较新的项目中沉淀出的一组架构模式pattern。部分模式比其他模式更流行文档中同时包含若干小幅改进以及许多大型应用中常见的目录。文档针对读者群体划出了清晰的适用边界Go 初学者、或只做个人小 side-project 的场景该布局完全不适用——从一个单独的main.go文件开始就足够了随着项目演进必须保持代码结构良好否则很快就会陷入难以维护的代码、大量隐藏的依赖和全局状态global state的泥潭项目参与人数越多稳健的结构就越重要。因此需要为“如何组织库和包”建立一种所有人一致的约定维护开源项目、或明确知道其他项目会 import 你的仓库代码时就需要公开包与私有代码即internal的明确区分使用方式上文档的原话是克隆仓库保留你需要的部分删除其余的Clonez le dépôt, gardez ce dont vous avez besoin et supprimez tout le reste !。目录存在并不意味着你必须全部使用——包括vendor在内没有任何模式是普适的。关于依赖管理文档给出了明确的时间线结论Go 1.14 起Go Modules 已可用于生产环境。除非有非常具体的理由否则应默认使用 Go Modules使用模块后无需再关心$GOPATH也无需预先规划项目放在哪个目录仓库内的 go.mod 就体现了模块约定module github.com/YOUR-USER-OR-ORG-NAME/YOUR-REPO-NAME默认假设仓库托管在 GitHub 上但这不是强制要求。模块路径可以是任意值只是路径的第一段第一个组件应当包含一个点——当前版本 Go 已不强制这一点但使用较旧版本 Go 时没有点可能导致构建失败整个布局是刻意保持通用的不试图强加某种特定的 Go 包结构它是一项社区协作工程发现新 pattern 或认为某个 pattern 需要更新时应通过提交 issue 参与完善。文档还给出了风格与命名的入门建议遇到命名、格式、风格问题时先跑一遍gofmt与golint再研读 Go 官方与社区的一系列命名指引如 Effective Go 的 Names 一节、Go Wiki 的 CodeReviewComments、rakyll 的《Style guideline for Go packages》以及 GopherCon 系列演讲Peter Bourgon 的工业级编程最佳实践、Kat Zien 的《How Do You Structure Your Go Apps》、Edward Muller 的《Go Anti-Patterns》等。二、仓库真实骨架一个可直接克隆的目录模板README_fr.md 所描述的布局在仓库本身中以“占位骨架”的形式完整落地。仓库根目录的真实结构如下各占位目录内以.keep文件保持空目录存在api/ assets/ build/ ├── ci/ (.keep) └── package/ (.keep) cmd/ └── _your_app_/ (.keep) configs/ deployments/ docs/ examples/ githooks/ init/ internal/ ├── app/_your_app_/ (.keep) └── pkg/_your_private_lib_/(.keep) pkg/ └── _your_public_lib_/ (.keep) scripts/ test/ third_party/ tools/ vendor/ website/ web/ ├── app/ (.keep) ├── static/ (.keep) └── template/ (.keep) go.mod Makefile .gitignore .editorconfig LICENSE.md README*.md其中几个配置文件直接印证了文档的原则go.mod仅两行——module github.com/YOUR-USER-OR-ORG-NAME/YOUR-REPO-NAME与go 1.19。这正是文档中“模块路径默认按 GitHub 托管书写、使用时替换为你自己的用户/组织与仓库名”的活例子。Makefile只有一行注释# note: call scripts from /scripts——刻意保持 Makefile 极简把构建、安装、分析等操作全部委托给/scripts目录下的脚本这与下文/scripts一节的设计意图完全一致。.gitignore忽略.DS_Store、二进制产物*.exe、*.dll、*.so、*.dylib、测试二进制*.test、覆盖率输出*.out、项目级 glide 缓存.glide/其中# vendor/一行被注释掉——默认不忽略 vendor需要时取消注释即可对应了“库项目不要提交依赖”的告诫。.editorconfig统一了charset utf-8、end_of_line lf、文件末尾换行与行尾去空格并对不同文件类型规定了缩进策略.go、Makefile、go.mod、go.sum及 Markdown 用 Tabyml/yaml/json用 2 空格JS/TS/Python 系用 4 空格保证多人协作时格式一致。三、Go 核心代码目录/cmd应用入口README_fr.md 对/cmd的定义是本项目的全部主应用。三条实操规则每个应用的目录名应当与你期望生成的可执行文件名一致例如/cmd/myapp对应可执行文件myapp不要把大量代码放在应用目录里。如果代码可以被其他项目 import 和复用移入/pkg如果代码不可复用、或你不想让别人复用放入/internal。文档特别提醒要对自己的意图保持显式否则你会惊讶于其他开发者如何“使用”你的代码常见做法是一个小小的main函数只负责 import 并调用/internal与/pkg中的代码别无其他。仓库中 cmd/README.md 补充了业界参照velero、moby、prometheus、influxdb、kubernetes、dapr、go-ethereum 等项目的cmd目录都遵循“极小的 main 函数 其余逻辑在包中”的模式。本仓库的占位目录cmd/_your_app_正是这一约定的落点。/internal编译器强制的私有代码/internal存放私有应用与库代码——即你不想被其他应用或库 import 的代码。文档强调一个关键实现事实这个模式是由 Go 编译器本身强制执行的可回溯至 Go 1.4 的 release notes而不是靠约定。两条常被忽略的细节internal不局限于顶层。你可以在项目树的任意层级放置多个internal目录可以额外增加一层结构来区分享用与非分享的内部代码应用自身代码放/internal/app如/internal/app/myapp各应用间共享的代码放/internal/pkg如/internal/pkg/myprivlib。这并非强制小项目尤其不必但它提供了关于包用途的视觉线索。本仓库的骨架正是后一种组织方式的模板internal/app/_your_app_/与internal/pkg/_your_private_lib_/见 internal/README.md其中还列举了 terraform、influxdb、jaeger、moby、minio 等采用internal的项目以及 hashicorp/waypoint 风格的internal/pkg实例。/pkg可声明为对外公开的库/pkg存放可被外部应用安全复用的代码例如/pkg/mypubliclib。文档给出了三条判断依据其他项目会 import 这些库并默认它们持续可用因此把代码放进/pkg前要三思真正保证包私有且不可 import 的方式是internal编译器强制/pkg的价值在于显式沟通“这里的代码可以放心被他人使用”。Travis Jeffery 的博客《Ill take pkg over internal》对两者的边界有更细致的讨论另一个收益是当根目录混杂了大量非 Go 组件时把 Go 代码集中到pkg便于运行各类 Go 工具GopherCon EU 2018《Best Practices for Industrial Programming》、Kat Zien 与 Massimiliano Pippi 的演讲都提到这一点。文档对pkg的态度非常诚实这不是一个被普遍接受的 pattern社区里有人不推荐它小型项目多一层嵌套未必有收益不必强用除非你真心想要。当项目变大、根目录开始杂乱尤其有大量非 Go 组件时再考虑引入。本仓库的 pkg/README.md 进一步交代了pkg目录的渊源——早期 Go 源码树自身用pkg组织包社区项目随之一路沿袭并给出了 containerd、istio、helm、kubernetes、moby、grafana、cockroach、etcd、datadog-agent、cilium 等一大批采用者的清单作为“社区常见但非共识”的注脚。对应占位目录为pkg/_your_public_lib_/。/vendor依赖目录与模块代理/vendor存放应用依赖可手工管理也可用你偏好的依赖管理工具或 Go 内置的 Modules 功能。文档给出的操作要点go mod vendor命令会为你生成/vendor目录若未使用 Go 1.141.14 起默认启用 vendor 模式执行go build时可能需要显式加上-modvendor标志如果你开发的是库library不要提交你的依赖。文档还交代了一个演进事实自 Go 1.13 起Go 启用了模块代理module proxy功能默认使用proxy.golang.org作为代理服务器。如果该机制满足你的需求与合规约束就完全不需要vendor目录。仓库的 .gitignore 中# vendor/处于注释状态vendor/目录当前只包含 vendor/README.md 的说明性内容——这正示范了“库项目不提交依赖”的默认姿态。四、服务与 Web 应用目录/apiAPI 规格与协议定义/api存放OpenAPI/Swagger 规格、JSON Schema 文件、协议定义文件。本仓库的 api/README.md 以 kubernetes 与 moby 的api目录为参照实例。这一目录面向的是“服务”型 Go 项目接口契约独立于实现存放便于多方按同一规格对接。/webWeb 前端组件/web存放Web 应用专属组件静态资源、服务端模板与 SPA。本仓库的骨架进一步细分了三个占位子目录web/app/单页应用SPA入口web/static/静态资源JS/CSS/图片等web/template/服务端渲染模板。见 web/README.md。对于非 Web 的纯后端项目整个/web目录可以直接删除——这正是“保留需要的、删除其余”原则的典型应用场景。五、应用通用目录/configs配置模板与默认配置/configs存放配置文件模板或默认配置confd与consul-template的模板文件也放在这里见 configs/README.md。它与 Go 代码目录的关系是模板化的配置在部署时由配置管理系统渲染而默认值随仓库版本化。/init系统初始化与进程监管/init存放系统初始化单元systemd、upstart、sysvinit以及进程管理器/监管器runit、supervisord的配置。服务化部署的 Go 应用通常需要一个 systemd unit 或 supervisord 配置来管理进程生命周期集中放在此目录可避免它们散落在仓库各处。/scripts把 Makefile 保持简单/scripts存放执行构建、安装、分析等各类操作的脚本。scripts/README.md 给出的核心理由是这些脚本让根目录的 Makefile 保持精简terraform 的 Makefile 是典型范例。这一设计在本仓库中得到了最直接的印证根 Makefile 全部正文只有一行注释# note: call scripts from /scripts——即 Makefile 只做入口具体逻辑全部下沉到scripts/。/build打包与持续集成/build面向打包Packaging与持续集成CI仓库内已落地两个子目录均含.keep占位/build/package云端AMI、容器Docker、操作系统deb、rpm、pkg等打包的脚本与配置/build/ciCItravis、circle、drone的脚本与配置。文档特别提醒某些 CI 工具如 Travis CI对配置文件的存放位置要求非常严格尽量把配置放在/build/ci并链接或复制到工具期望的位置如果做不到放在根目录也无妨。/deployments基础设施与编排/deployments存放IaaS、PaaS、系统与容器编排的部署模板和配置docker-compose、kubernetes/helm、mesos、terraform、bosh 等。文档补充了一个命名变体在部分项目主要是经 Kubernetes 部署的应用中这个目录叫/deploy。/test外部测试应用与测试数据/test存放额外的外部测试应用与测试数据内部结构可自由组织。文档给出的两条与 Go 工具链直接相关的事实较大的项目建议设置数据子目录例如/test/data或者使用/test/testdata——testdata是 Go 工具链会自动忽略的目录名适合放置不参与构建的测试数据Go 同时忽略以.或_开头的目录和文件这为测试数据目录命名提供了更大灵活性。build/README.md 与 test/README.md 分别以 cockroach 与 openshift/origin测试数据位于/testdata子目录作为参照实例。六、其他通用目录目录用途据 README_fr.md仓库内补充证据/docs用户与设计文档在 GoDoc 生成文档之外docs/README.md 列举 hugo、openshift、dapr 实例/tools项目支撑工具这些脚本可以 import/pkg与/internal的代码tools/README.md 列举 istio、openshift、dapr 实例/examples应用与/或公共库的使用示例examples/README.md 列举 nats.go、docker-slim、packer 实例/third_party外部辅助工具、fork 代码与其他三方工具如 Swagger UIthird_party/README.md/githooksGit hooksgithooks/README.md/assets随仓库分发的其他资源图片、logo 等assets/README.md/website若不使用 GitHub Pages项目网站数据放在此website/README.md 列举 vault、perkeep 实例其中/tools值得单独强调文档明确指出 tools 中的脚本可以import/pkg和/internal的代码——即工具链代码与业务代码共享同一模块边界这是它与/cmd对外部使用者而言只是入口在职责上的关键差别。七、/src一个应当避免的目录README_fr.md 专门辟出一节告诫Go 项目中不应出现根级/src目录。其理由与常见误解出现src的 Go 项目通常源于开发者来自 Java 世界——这是 Java 的惯例文档直言你并不希望自己的 Go 代码看起来像 Java不要把根级/src与GOPATH 工作区中的/src混为一谈环境变量$GOPATH指向当前工作区非 Windows 系统默认为$HOME/go该工作区包含/pkg、/bin、/src三个目录你的项目本身位于工作区的/src子目录下。若项目里再建一个/src代码文件的完整路径会变成/some/path/to/workspace/src/your_project/src/your_code.go这样的双重嵌套文档补充了一个版本事实自 Go 1.11 起项目可以放在 GOPATH 之外——但这仍然不构成使用/src目录的理由本仓库的 go.mod 也表明当前模块模式下项目位置完全自由。八、命名、风格与质量徽章在“命名与组织”之外README_fr.md 的 Badges 一节推荐了面向开源仓库的三组质量标识引用时把徽章指向的仓库地址替换为你自己的项目地址即可Go Report Card用gofmt、go vet、gocyclo、golint、ineffassign、license、misspell等命令扫描代码并出具评分徽章——这份工具清单本身就是 Go 项目质量检查的常用基线Pkg.go.devGo 文档发现平台可通过其徽章生成工具为模块创建徽章原 GoDoc 在线文档服务已被其取代Release 徽章展示项目最新版本号。配套的命名与风格自查流程如前所述是gofmtgolint先行再对照官方与社区命名指引。.editorconfig 则从编辑器层面固化了这套约定。九、实操要点克隆与裁剪模板把 README_fr.md 全文收敛为可执行的落地步骤克隆仓库后先做减法以 go.mod 的模块路径占位为起点替换为你的用户/组织/仓库名按项目类型删除用不到的目录——非 Web 项目删/web纯库项目删/cmd并确认不提交vendor/参考 .gitignore 中被注释的# vendor/行无外部依赖管理诉求的项目删/third_party代码放置三问能被外部复用的公共库 →pkg/不想被复用的内部逻辑 →internal/可用internal/app与internal/pkg二级结构参照本仓库internal/app/_your_app_、internal/pkg/_your_private_lib_占位应用入口 →cmd/且main保持极小构建逻辑下沉根 Makefile 只留入口注释参照本仓库 Makefile构建/安装/分析脚本放/scripts打包与 CI 配置分别进/build/package与/build/ci依赖管理默认走 Go ModulesGo 1.14 生产可用确需离线/受限环境时go mod vendor生成/vendor旧版本工具链配合-modvendor构建部署与初始化资产归位IaaS/PaaS/K8s/Helm/Terraform 配置进/deployments或/deploysystemd/supervisord 单元进/initconfd/consul-template 模板进/configs始终避免根级/src测试数据用testdata或以./_前缀命名以被 Go 工具链忽略。最后README_fr.md 的 Notes 一节说明一个包含可复用代码、脚本与配置、不那么通用的项目模板正在社区制作中关注该仓库动态可以获取后续演进。十、附录多语言文档索引该布局文档维护了 19 个语言版本仓库内均可直接查阅英文、한국어、简体中文、正體中文、Français、日本語、Português、Español、Română、Русский、Türkçe、Italiano、Tiếng Việt、Українська、Bahasa Indonesia、हिन्दी、Беларуская另有 README_fa.md、README.md 等版本与 LICENSE.md 协议文件。本文为法语版的中文展开各节表述与 README_fr.md 原文一一对应实现细节则以仓库内的目录骨架与各目录 README 为准。【免费下载链接】project-layoutStandard Go Project Layout项目地址: https://gitcode.com/GitHub_Trending/pr/project-layout创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考