Go 项目最佳实践
作者 | 陌无崖
转载请联系授权
Go 项目最佳实践
Go应用程序应遵循的结构是一个有争议的主题。有些人坚持认为,每个人都应该对每个项目都遵循众所周知的golang-standards / project-layout结构。
但是,随着Go模块的引入成为处理依赖关系的标准,这种结构开始提出挑战。按照传统结构,您会发现结构中的某些文件夹无法访问内部或pkg之类的文件夹,并且您必须实施一些骇人听闻的解决方案才能使它们按原样工作。
在本文中,我将介绍在按新的世界顺序构建Go应用程序时可以选择的一系列选项。
小型应用-平面结构
每个项目都从小规模开始,并逐渐成长,这取决于它的成功程度或开发人员愿意为之贡献多少时间。
application/
- main.go
- main_test.go
- utils.go
- utils_test.go
- ...
强烈建议您在上述情况下从扁平文件夹结构入手。通过使项目的结构从一开始就简单易行,作为开发人员,您可以专注于尽可能快地向目标受众提供最高价值的功能,而不会产生复杂结构的认知开销。
我经常看到开发人员在交付任何真正有价值的东西之前,在项目的早期阶段花费更多的时间来安排和重新安排他们的代码库,并最终导致开发人员或开发人员团队之间的反馈循环更长。您的目标受众。
益处
这种扁平文件夹结构在开发时非常理想:
- 微服务-以分布式方式部署的微型应用程序,其构建目的是做一件事情,而只能做一件事情。
- 小型工具和库-专注于很好地完成少数任务的命令行工具或小型库。
这种结构的例子
让我们看一下此结构工作原理的一些示例: tidwall / gjson-这个项目几乎完美地说明了一个令人难以置信的极简主义结构如何仍能成功完成项目的观点。他们从一开始就将所有内容保持在令人难以置信的平坦状态,并没有使事情变得过于复杂,同时专注于为使用该项目的人们提供真正的价值。
- go-yaml / yaml-另一个非常酷的项目,具有完全平坦的项目结构。
中/大型应用程序-模块化
随着项目规模和复杂性的增长,您很快就会发现它开始超出平面结构,这是您应该开始考虑模块化代码库的时候了。
让我们以为网站提供动力的REST API为例。该REST API可能具有处理用户注册和登录的端点,以及另一个以类似CRUD的方式处理用户内容的组。
在这一点上,我们应该开始考虑将应用程序分解为功能性语义组,并可能将这些组件之间共享的所有核心逻辑集中到项目中的共享包中。
rest-api/
- main.go
- user/
- - user.go
- - login.go
- - registration.go
- articles/
- - articles.go
- utils/
- - common_utils.go
这种结构的例子
这里只是一些采用了这种结构的Go项目。
google / go-cloud-这是采用此结构的项目的一个很好的例子。他们已将项目分解为每个IAAS云提供商的程序包,并且每个程序包都包含与该特定云提供商有关的所有代码。
hashicorp / consul-这是选择采用模块化方法的大型项目的另一个很好的例子。
ipfs / go-ipfs-IPFS是用Go编写的非常酷的对等文件系统,它基于以前的系统(例如Git和BitTorrent)。同样,他们在开发系统时选择采用模块化方法。
gohugoio / hugo-非常好用的框架,目前已用作本网站的后端!
成熟的项目
您绝对会看到符合旧项目结构的项目,但这是这些应用程序开发时间的副产品。
诸如Hashicorp的Terraform或Google自己的Kubernetes之类的大型应用程序倾向于保留旧式结构的残留物,当$ GOPATH成为最高版本时,这种残留物效果很好。您会看到它们仍然具有内部和pkg文件夹,其中包含项目的某些内部工作。
这种结构运行得非常好,使开发人员能够为开发社区提供令人难以置信的价值,但是我认为,随着Go Modules开始变得越来越流行,我们将开始看到这些应用程序从更传统的结构迁移到传统结构。较新的结构。
拆分项目
在特定的一点之后,将项目的某些有意义的部分完全切入具有其生命周期的单独存储库中可能是有意义的。
这将具有其自身的一系列弊端,例如管理整个项目资产中的更新时增加的开销。但是,这也意味着您的项目对于想要贡献和帮助的项目新手来说将更容易消化。
结论
希望本文对您的开发工作有所帮助,并在您开始为下一个Go项目建模时给您一些想法!
这些是我自己的发现,基于我个人在日常工作中开发服务和服务经纪人的个人开发经验。使用这些结构时,您自己的里程可能会有所不同,但我很乐意在下面的评论部分中听到您对如何构建Go应用程序的想法和提示!
- 原文链接:https://tutorialedge.net/golang/go-project-structure-best-practices/
本文为Golang官方博客部分文章的外文翻译,官方案例更加有料哦
- Nodejs学习笔记(三)——一张图看懂Nodejs建站
- 不规则图形的碰撞检测
- 自学WP7第一个例子:时钟
- 教您最简单粗暴的MATLAB入门级爬虫2
- 前台JS(Jquery)调用后台方法 无刷新级联菜单示例
- 项目中对图片的缩放和水印效果
- 照虎画猫写自己的Spring——自定义注解
- 数据分析进阶课程笔记(六)
- 微信发布重磅更新!上线小游戏,小程序间可快速切换
- 鼠标点击层以外的地方层隐藏
- WCF后续之旅(11): 关于并发、回调的线程关联性(Thread Affinity)
- WCF后续之旅(11): 关于并发、回调的线程关联性(Thread Affinity)
- 解决文本框在updatepanel中得到焦点,输入法不能切换到中文的问题
- 得到真实外网IP、IP所在国家、省份、地区
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 神经网络架构搜索——可微分搜索(SGAS)
- 神经网络架构搜索——可微分搜索(Fair-DARTS)
- 一帧图像的Android之旅 :应用的首个绘制请求
- Mac免密码登录linux服务器
- 目标检测算法YOLO-V2详解
- 神经网络架构搜索——可微分搜索(Noisy DARTS)
- 教你使用 Jacoco 统计服务端代码覆盖率
- 如何在树莓派4B上设置EMQX开机自启动
- 如何使用 Ktor 快速开发 Web 项目
- 神经网络架构搜索——二值可微分搜索(BATS)
- UEFI 原理与编程 1 - UEFI开发环境EDK2搭建
- 【Unity】瞎做个宝石迷阵吧!(1)——构建场景
- VUE组件传值案例讲解
- 【JAVA】来写个JAVA的HelloWorld吧!
- 如何发布自己的项目到Maven中央仓库?