ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Standard Go Project Layout 详解:project-layout 中 cmd / internal / pkg 等目录约定的完整实践指南

Standard Go Project Layout 详解:project-layout 中 cmd / internal / pkg 等目录约定的完整实践指南 Standard Go Project Layout 详解project-layout 中 cmd / internal / pkg 等目录约定的完整实践指南【免费下载链接】project-layoutStandard Go Project Layout项目地址: https://gitcode.com/GitHub_Trending/pr/project-layout本文基于 project-layout 仓库的白俄罗斯语版核心文档 README_be.md 撰写系统讲解 Standard Go Project Layout标准 Go 项目布局的每个目录约定、适用前提与取舍原则并结合仓库自身的目录树、go.mod 和各目录说明文件逐项验证模板的实际形态。读完本文你可以为中小型 Go 项目快速设计一套可扩展、语义清晰的目录结构明确哪些目录必须保留、哪些目录不要创建以及如何通过internal机制在编译器层面保护私有代码。一、模板定位社区约定而非官方标准README_be.md 在开头就明确了这套布局的三个定性理解它们是后续所有目录约定成立的前提内容是基础的模板只关注项目的整体目录结构不约束每个目录内部应该放什么也不追求 Clean Architecture 之类的深层架构设计抽象层次是基础的它非常高层不涉及如何进一步细化组织的细节不是 Go 核心团队定义的官方标准它是一组 Go 生态中常见有历史沿袭也有新兴的项目放置模式其中一些模式比另一些更流行并附带若干常见于足够大的真实应用中的辅助目录。官方 Go 文档中的Organizing a Go module模块组织页面同样给出了internal与cmd等目录模式的一般性建议模板与官方指引并不冲突。文档同时给出了一条非常直接的使用边界建议如果你在学习 Go或者只是构建一个 PoC 或简单项目这套布局属于过度设计。从一个main.go文件和go.mod开始就足够了。随着项目成长再逐步引入结构化的包管理方式当多人协作、出现开源项目或被其他项目导入时引入internal私有包就很重要。文档给出的落地方式很务实——克隆本仓库保留你需要的目录删除其余全部。存在即需要使用这个假设不成立没有任何一个模式适用于所有项目连vendor都不是普适的。本仓库自身就是这套文档的活样例。从仓库根目录结构可以看到模板把每条约定都物化成了占位目录├── cmd/_your_app_ # 可执行应用占位 ├── internal/ │ ├── app/_your_app_/ # 内部应用代码占位 │ └── pkg/_your_private_lib_/ # 内部私有库占位 ├── pkg/_your_public_lib_/ # 对外公开库占位 ├── web/{app,static,template} # Web 组件占位 ├── api/ configs/ deployments/ docs/ examples/ githooks/ ├── init/ scripts/ test/ third_party/ tools/ website/ assets/ ├── go.mod └── Makefile值得注意的是占位目录名采用了_your_app_、_your_private_lib_这类以下划线_开头的命名。文档在讲解/test目录时说明过 Go 工具链会忽略以.或_开头的目录与文件——从源码结构看模板正是利用了这一规则即使克隆者没有替换占位目录名Go 工具也会自动忽略它们保证模板仓库本身始终可构建。此外这是一项社区协作工程发现新模式或认为现有模式需要更新时应提交 issue。仓库根目录同时维护了包括白俄罗斯语在内的 18 个语言版本的 READMEREADME_ko.md、README_zh.md、README_ru.md、README_be.md 等各版本内容同步自同一份核心文档。二、go.mod 与 Go Modules模板的基线假设文档指出自 Go 1.14 起 Go Modules 已可用于生产环境除非有具体理由否则应使用 Modules——此时你不需要再关心$GOPATH或项目放在哪里。仓库根目录的 go.mod 展示了模板的基线形态module github.com/YOUR-USER-OR-ORG-NAME/YOUR-REPO-NAME go 1.19围绕这份go.mod文档给出了几条关键说明模板中的go.mod默认假设项目托管在 GitHubgithub.com/用户/仓库的模块路径但这不是强制要求模块路径可以是任意值模块路径的第一个组件按惯例应包含一个点如github.com。当前版本的 Go 已不再强制这一点但如果使用稍旧的 Go 版本缺少点号的模块路径会导致构建失败——遇到此类问题不必意外该模板刻意保持通用不试图强加某种具体的 Go 包结构。三、Go 核心目录/cmd、/internal、/pkg、/vendor/cmd项目的主应用入口cmd存放项目的主应用main applications每个应用子目录的名字应当与你期望生成的可执行文件名字一致例如/cmd/myapp不要往应用目录里堆大量代码如果你认为代码可以被其他项目导入复用应放到/pkg如果代码不可复用或你不想让别人复用应放到/internal。文档特别提醒你会对别人拿你的代码做什么感到惊讶所以请明确表达你的意图常见的最佳形态是一个很小的main函数只导入并调用/internal与/pkg中的代码不做其他事情。各目录的说明文件对这条约定做了重复强化cmd/README.md 除说明约定外还罗列了一批遵循该模式的大型仓库作为参照。模板中的占位目录cmd/_your_app_/即对应一个最小main应用的位置。/internal编译器强制的私有代码这是整个布局中唯一具有编译器级强制力的约定核心要点包括internal存放私有应用与库代码即你不希望其他项目导入的代码该模式由 Go 编译器自身强制执行Go 1.4 起把包放进internal目录后除非共享公共祖先路径否则其他包无法导入它它也是 Go 官方文档中唯一被命名并享有特殊编译器处理的目录不限于顶层项目树的任何层级都可以有多个internal目录可选的进一步结构划分小项目非必需但有助于视觉上传达包的使用意图/internal/app例如/internal/app/myapp放实际应用代码/internal/pkg例如/internal/pkg/myprivlib放这些应用共享的内部代码。internal/README.md 重复了上述约定并列举了采用该模式的大型仓库本仓库中internal/app/_your_app_/与internal/pkg/_your_private_lib_/两个占位目录正是文档推荐的两级结构的直接体现。/pkg对外可导入的公开库pkg存放可以被外部应用使用的库代码例如/pkg/mypubliclib。其他项目导入这些库后默认它们可用因此放置到这里之前要三思必须澄清的层次关系internal是靠 Go 语言机制强制私有化的更可靠手段而/pkg的价值在于显式传达此目录代码可供他人安全使用的意图另一个实用动机当根目录包含大量非 Go 组件与目录时把 Go 代码集中到pkg一处便于运行各类 Go 工具这不是普遍接受的模式——社区中有人推荐、有人反对每有一个流行仓库用它就能找到十个不用的项目很小、额外一层嵌套收益不大时完全可以不用等根目录变得拥挤尤其非 Go 组件多时再考虑起源早期 Go 源码仓库自身用pkg存放打包后的包社区项目随后效仿了这一模式。pkg/README.md 额外补充了使用/不使用该模式都不影响更多人理解你的意图的社区共识并列出了一长串采用pkg布局的知名开源仓库便于读者对照自己熟悉的代码库确认模式形态本仓库的占位目录pkg/_your_public_lib_/即公开库的预留位置。/vendor依赖存放按需使用存放应用依赖可手工管理也可用依赖管理工具如今内建的 Go Modules。执行go mod vendor即可自动生成/vendor目录若 Go 版本不是 1.141.14 起默认启用 vendor 模式go build时可能需要额外加-modvendor标志如果你在构建的是库library不要提交应用依赖自 Go 1.13 起还启用了模块代理module proxy功能默认使用官方代理proxy.golang.org。如果代理满足你的全部需求与约束vendor目录可以完全不需要。四、服务类与 Web 应用目录/api 与 /web/api存放服务的接口契约类文件OpenAPI/Swagger 规范文件JSON schema 文件协议定义文件。api/README.md 对该目录的职责做了同样的说明并给出遵循该模式的大型仓库参考。/web存放 Web 应用特有的组件静态 Web 资源static assets服务端模板server side templatesSPA单页应用。本仓库中web/下预置了三个占位子目录web/app、web/static、web/template正好对应上述 SPA 代码、静态资源与服务端模板三类内容。五、通用应用目录/configs、/init、/scripts、/build、/deployments、/test/configs配置文件模板或默认配置confd或consul-template的模板文件也放在这里。/init系统初始化与进程管理配置系统 initsystemd、upstart、sysv进程管理器/守护器runit、supervisord。/scripts执行构建、安装、分析等各类操作的脚本。这些脚本的意义在于保持根目录 Makefile 小而简单——本仓库的 Makefile 全文只有一行注释正是这条约定的直接示范# note: call scripts from /scripts即所有具体操作下沉到 scripts/README.md 对应的/scripts目录中根级 Makefile 仅作为入口提示。/build打包Packaging与持续集成CI分为两个子目录/build/package云AMI、容器Docker、操作系统deb、rpm、pkg的打包配置与脚本/build/ciCI 工具travis、circle、drone的配置与脚本。注意部分 CI 工具对配置文件位置非常挑剔应尽量把配置放在/build/ci并链接到 CI 工具期望的位置在可行的情况下。/deploymentsIaaS、PaaS、系统与容器编排的部署配置和模板docker-compose、kubernetes/helm、terraform。注意有些仓库尤其是用 kubernetes 部署的应用会把此目录命名为/deploy。/test额外的外部测试程序与测试数据目录内部结构可自由组织大项目建议设一个数据子目录例如/test/data或/test/testdata当需要 Go 忽略其中内容时关键规则Go 会忽略以.或_开头的目录或文件因此测试数据目录的命名有更大灵活性test/README.md 给出了把测试数据放在/testdata子目录的典型仓库示例。六、其他目录/docs、/tools、/examples、/third_party、/githooks、/assets、/website目录职责仓库内说明/docs设计与用户文档godoc 生成的文档之外的补充docs/README.md/tools本项目的支撑工具这些工具可以导入/pkg与/internal中的代码—/examples应用与/或公开库的使用示例examples/README.md/third_party外部辅助工具、fork 的代码及其他第三方工具如 Swagger UI—/githooksGit 钩子—/assets伴随仓库的其他资源图片、logo 等—/website不使用 GitHub Pages 时项目站点数据的存放处website/README.md其中/tools与/cmd的边界值得注意cmd面向最终交付的可执行程序而tools面向开发过程本身的辅助程序且后者明确允许复用pkg/internal中的实现。七、反模式不要创建 /src 目录文档用单独一节Kаталогі, якіх у вас не павінна быць / Directories You Shouldnt Have警告/src一些 Go 项目确实有src文件夹通常发生在开发者来自 Java 世界那里是通用模式的时候。如果可能不要照搬这个 Java 模式——你不想让 Go 代码或 Go 项目看起来像 Java 项目不要混淆项目级/src与 Go 工作区使用的/src$GOPATH环境变量指向当前工作区非 Windows 系统默认$HOME/go该工作区包含顶层的/pkg、/bin、/src三个目录你的实际项目会落在其/src之下。因此项目内再建/src代码路径会退化成.../workspace/src/your_project/src/your_code.go这种双重嵌套尽管 Go 1.11 起项目可以放在GOPATH之外这仍然不代表/src是好的布局选择。八、命名、格式、静态检查与徽章文档对风格工具链的建议是遇到命名、格式与样式问题先运行gofmt和staticcheck。原来的标准 lintergolint已弃停deprecated且不再维护应使用受维护的 linter如 staticcheck替代。文档同时指向官方风格材料Effective Go 命名章节、包命名博客、Code Review Comments wiki 等以及多篇 GopherCon 关于包命名与工业级编程实践的演讲并附有一篇关于面向包设计Package-Oriented-Design与架构分层的中文文章。仓库根目录维护的徽章Badges部分说明了开源 Go 项目常见的四类徽章克隆后替换为自己的项目引用即可Go Report Card扫描代码的gofmt、go vet、gocyclo、golint、ineffassign、license、misspell七项检查GoDoc 徽章提供 godoc 生成文档的在线版本原文档中该条目已被删除线标记为弃用;Pkg.go.dev 徽章Go 代码发现与文档的新入口可用其徽章生成工具创建Release 徽章展示项目最新版本号。九、采用路径与落地清单把 README_be.md 的核心主张浓缩为可执行的动作清单学习/PoC/小项目只用main.gogo.mod跳过本模板项目开始变复杂从 go.mod 出发模块路径可为任意值首组件惯例含点有多个可执行程序按可执行文件名建cmd/app子目录main函数保持极小参见 cmd/README.md出现私有实现放进internal需要再细分时用internal/app应用与internal/pkg共享内部库两级参见 internal/README.md对外提供可导入的库放进pkg并理解它传达的是可安全导入的意图而非强制参见 pkg/README.md;构建产物与依赖需要离线/锁定依赖时go mod vendorGo 1.14 以下构建加-modvendor库项目不提交依赖模块代理可用时直接省略 vendor运维与周边配置模板进configssystemd/supervisord 单元进init构建安装脚本进scripts并让根 Makefile 保持极简打包与 CI 进build/package、build/ci部署编排进deployments明确不做不建/src避免 Java 式目录与 Go 工作区GOPATH/src混淆。文档末尾Notes还预告一个更有主见的项目模板——附带可复用的示例配置、脚本与代码——仍处于开发中。对希望进一步收敛约定的团队可以关注该方向后续产出在此之前本文覆盖的这套通用布局连同仓库中各目录说明文件api/README.md、scripts/README.md、test/README.md、docs/README.md、examples/README.md 等已经构成了一套完整、可复制、可裁剪的 Go 项目目录规范基线。【免费下载链接】project-layoutStandard Go Project Layout项目地址: https://gitcode.com/GitHub_Trending/pr/project-layout创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表