PHP转Go很丝滑开发框架设计思路-把php优秀设计借鉴到Go框架设计里面-保留php开发习惯又能提供高软件性能

news2024/9/23 9:22:19

框架从以下设计要求使得达到有快速开发有又保证软件性能。框架要满足我们追求的大道至简、简单易容、减少开发者心智负担、快乐开发目标。

框架代码结构简单

框架设计的结构一定要简单,简单才能让新手容易上手、后续代码维护成本低、集成大项目才容易(不至于混乱)。目录结构如下,其中app目录使我们业务代码位置,app之外都是框架固定好的设计,开发时不用去动。app下每一个文件夹表示一个模块,如:admin、business后台管理接口,根据业务可以添加weixin、douyinapp等模块,让扩展变得简单。

同样的在模块内容也是可以添加文件夹表示一个业务类型,比如:在business模块下的文章(创建一个article文件夹),文章类也可能有文章管理、文章分类、文章评论,这些就在article文件夹里添加cate.go=编写文章分类接口,comments.go=编写文章评论接口,其他功能通用添加自己.go文件编写对应业务。

├── app                       # 应用目录
│   ├── admin                 # 后台管理应用模块(安装saas时存在、不安装则删除)
│   ├── business              # 业务端应用模块
│   ├── common                # 公共应用模块
│   └── controller.go         # 应用控制器
├── devsource                 # 开发静态资源(安装界面、代码生成模板)
├── resource                  # 静态资源及配置文件(发布应用带上)
├── runtime                   # 运行时文件(项目运行时自己生成)
├── utils                     # 框架核心代码及工具包
├── go.mod                    # 依赖包管理工具
├── go.sum         
├── main.go                   # main函数       
├── runner.conf               # fresh热编译配置文件
└── README.md                 # 项目介绍

后端路由可根据接口位置生成

从上面加粗例子创建的文章类,框架根据创建接口目录层级自行生产接口的请求地址并注册到服务上,比如:文章分类的获取分类列表、添加、删除,分别生成地址为:business/article/cate/getList、business/article/cate/save、business/article/cate/del。同样的评论也是一样的:business/article/comments/save,路径会根据它所在文件名生成。

为什么我们要把强调路由自动生成,因为Go的很多框架路由都是手动配置的,我们使用的Gin框架也是手动添加路由,为了避免手动添加工作量,自动生成还是很必要的,最重要的是,手动添加多人协同开发,可能存在填写一样的路由名,导致路由重复。根据目录和文件名生成避免重复,同时路可以更加api接口层级快速找到接口位置,方便通过接口找到代码,在后期维护即看其他人写代码也能快速定位代码位置。

orm操作链式操作习惯和php一样舒服

Go是强类型语言,在存取数据是需要对应数据字段类型去接收和提交数据。所以开发时需要写对应数据表数据结构,这个在开发时很费时,框架需要像php简单$变量很难做到。市面很多Go的ORM只有数据结构存取数据,每个操作都写数据表结构体很烦,所以我们框架一定集成一个需要要数据结构要求的ORM,当然我们集成的ORM是两者都兼容,这样习惯用结构的开发者也是可以使用结构,因为有些提供给其他人使用,有结构体的数据可以在取数据时候知道有哪些字段及数据类型。

看看我们数据数据库操作:

  • 获取全部数据
list, err := gf.Model("createcode_product_cate").Where("status",0).
Fields("id,name,status,createtime").Order("id asc").Select()
  • 保存数据
//添加数据有三种方法
//1.写入的数据中存在主键或者唯一索引时,返回失败,否则写入一条新数据
addId, err := gf.Model("createcode_product_cate").Data(param).InsertAndGetId()
//2.用于写入数据时并直接返回自增字段的ID
res, err := gf.Model("createcode_product_cate").Data(param).Insert()
//3.写入的数据中存在主键或者唯一索引时,更新原有数据,否则写入一条新数据
res, err := gf.Model("createcode_product_cate").Data(param).save()
  • 更新数据
res, err := gf.Model("createcode_product_cate").Data(param).Where("id", f_id).Update()
  • 删除数据
	res2, err := gf.Model("createcode_product_cate").Where("id", 1).Delete()

更多orm操作到:orm开发文档

开发一个接口示例:

package createcode

import (
	"gofly/utils/gf"
)

// 关联的分类
type Productcate struct{}

func init() {
	fpath := Productcate{}
	gf.Register(&fpath, fpath)
}

// 获取列表
func (api *Productcate) GetList(c *gf.GinCtx) {
	list, err := gf.Model("createcode_product_cate").Where("status", 0).Fields("id,name,status,createtime").Order("id asc").Select()
	if err != nil {
		gf.Failed().SetMsg(err.Error()).Regin(c)
	} else {
		gf.Success().SetMsg("获取列表").SetData(list).Regin(c)
	}
}


// 更新状态
func (api *Productcate) UpStatus(c *gf.GinCtx) {
	param, _ := gf.RequestParam(c)
	res2, err := gf.Model("createcode_product_cate").Where("id", param["id"]).Data(param).Update()
	if err != nil {
		gf.Failed().SetMsg("更新失败!").SetData(err).Regin(c)
	} else {
		msg := "更新成功!"
		if res2 == nil {
			msg = "暂无数据更新"
		}
		gf.Success().SetMsg(msg).SetData(res2).Regin(c)
	}
}

// 删除
func (api *Productcate) Del(c *gf.GinCtx) {
	param, _ := gf.RequestParam(c)
	res2, err := gf.Model("createcode_product_cate").WhereIn("id", param["ids"]).Delete()
	if err != nil {
		gf.Failed().SetMsg("删除失败").SetData(err).Regin(c)
	} else {
		gf.Success().SetMsg("删除成功!").SetData(res2).Regin(c)
	}
}

现在web应用计划都采用前后端分离,所以只需保证后端开发接口速度快即可,前端不管那个语言可以使用vue、react等框架。我们框架基于Go语言简单基础上设计得让开发变得简单。我们使用过其他框架,有些参考java框架集成,还是集成过于重。我们还是喜欢大道至简这个设计思路,开发本来简单,写程序应该是一种享受,开发框架也是需要简单,不能增加开发者开发时的心里负担。

题外话这里引用他人一句话: Golang哲学就是"少便是多", 志在减少开发者的心智负担. 不过再好的语言也敌不过"人", 请接受Golang的风格 否则写出PHPGo, JavaGo真是作茧自缚。

我们大家喜欢Go,就是Go的设计者们初心就是为了减少开发者的心智负担。所以GoFly框架也是志在简洁简单、开发舒服、减少开发者心智负担。开发者朋友我们一起为快乐编程目标奋斗吧!我们在GoFly全栈开发社区等大家哦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2157176.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring6梳理10—— 依赖注入之注入数组类型属性

以上笔记来源: 尚硅谷Spring零基础入门到进阶,一套搞定spring6全套视频教程(源码级讲解)https://www.bilibili.com/video/BV1kR4y1b7Qc 目录 10 依赖注入之注入数组类型属性 10.1 创建Emp实体类,Dept实体类 10.2…

Java 每日一刊(第15期):内部类

文章目录 前言内部类成员内部类(Member Inner Class)静态内部类(Static Nested Class)局部内部类(Local Inner Class)匿名内部类(Anonymous Inner Class) 内部类的详细对比内部类字节…

浅谈Spring Cloud:Nacos的配置

Nacos,一个更易于构建云原生应用的动态服务发现,配置管理和服务管理平台。所以Nacos是⼀个注册中心组件,但它又不仅仅是注册中心组件。 目录 安装 注册 负载均衡 环境隔离 配置管理 搭建集群 安装 在官网下载好安装包解压后&#xf…

深度学习01-概述

深度学习是机器学习的一个子集。机器学习是实现人工智能的一种途径,而深度学习则是通过多层神经网络模拟人类大脑的方式进行学习和知识提取。 深度学习的关键特点: 1. 自动提取特征:与传统的机器学习方法不同,深度学习不需要手动…

手机在网状态查询接口如何用Java进行调用?

一、什么是手机在网状态查询接口? 手机在网状态查询接口,又叫运营商在网状态查询,手机号在网状态查询,传入手机号码,查询该手机号的在网状态,返回内容有正常使用、停机、在网但不可用、不在网(…

【网络】高级IO——epoll版本TCP服务器初阶

目录 前言 一,epoll的三个系统调用接口 1.1.epoll_create函数 1.1.1.epoll_create函数干了什么 1.2. epoll_ctl函数 1.2.1.epoll_ctl函数函数干了什么 1.3.epoll_wait函数 1.3.1.epoll_wait到底干了什么 1.4.epoll的工作过程中内核在干什么 二,…

【Elasticsearch系列廿】Logstash 学习

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

PostgreSQL 的log_hostname 参数测试

PostgreSQL 的log_hostname 参数测试 log_hostname 是 PostgreSQL 配置文件 (postgresql.conf) 中的一个参数,用于控制是否在日志条目中记录客户端主机名。默认情况下,PostgreSQL 只记录客户端的IP地址,而 log_hostname 参数允许数据库管理员…

【最基础最直观的排序 —— 冒泡排序算法】

最基础最直观的排序 —— 冒泡排序算法 冒泡排序(Bubble Sort)是一种计算机科学领域的较简单的排序算法,属于交换排序。其基本思想是在待排序的一组数中,将相邻的两个数进行比较,若前面的数比后面的数大就交换两数&am…

农产品商城系统小程序的设计

管理员账户功能包括:系统首页,个人中心,用户管理,产品分类管理,热销农产品管理,订单管理,系统管理 微信端账号功能包括:系统首页,热销弄产品,网站公告&#…

基于c++实现的简易shell

代码逻辑 核心思想 解析命令行,拆解命令及其选项创建子进程,在子进程中执行命令如果是前台执行命令,则父进程就阻塞等待子进程中命令执行结束后回收子进程的资源如果是后台执行命令,则父进程不进行阻塞等待,可继续向下…

STM32 软件触发ADC采集

0.91寸OLED屏幕大小的音频频谱,炫酷! STM32另一个很少人知道的的功能——时钟监测 晶振与软件的关系(深度理解) STM32单片机一种另类的IO初始化方法 ADC是一个十分重要的功能,几乎任何一款单片机都会包含这个功能&a…

记一次MySQL索引不当引发死锁问题

一、前言 在并发量很低的情况下,mysql 的响应时延一切正常,一旦并发量上去了,mysql就会出现死锁的情况,你有没有遇到过?到底是是什么原因导致的呢,让我们一起看看真实的案例。 二、遇到的问题 先介绍一下…

LabVIEW提高开发效率技巧----利用第三方库和工具

LabVIEW开发不仅依赖于自身强大的图形化编程能力,还得益于其庞大的用户社区和丰富的第三方库。这些工具和库能够帮助开发者快速解决问题,提升开发效率,避免从头开始编写代码。 1. LabVIEW工具网络(NI Tools Network) …

MateBook 16s 2023在Deepin下开启性能模式,调节风扇转速到最大,全网首发!

方法 在Deepin下按住Fnp快捷键,开启性能模式。 验证 首先去debian下载acpi-call-dkms https://packages.debian.org/sid/all/acpi-call-dkms/download 然后使用root用户执行: apt install --simulate ./acpi-call-dkms_1.2.2-2.1_all.deb apt inst…

LeetCode 面试经典150题 191.位1的个数

Java中的算术右移和逻辑右移的区别 题目:编写一个函数,获取一个正整数的二进制形式并返回其二进制表达式中设置位的个数(也被称为汉明重量)。 设置位的个数即二进制中1的个数。 思路:方法一:因为正数的原…

基于阿里云免费部署Qwen1-8B-chat模型并进行lora参数微调从0到1上手操作

文章目录 一、申请资源二、创建实例三、克隆微调数据四、部署Qwen1-8B-chat模型1、环境配置2、模型下载3、本地模型部署 五、模型微调1、拉取Qwen仓库源码2、微调配置3、合并微调参数4、本地部署微调模型 一、申请资源 阿里云账号申请PAI资源详细教程我已于部署ChatGLM3时写过…

Golang | Leetcode Golang题解之第430题扁平化多级双向链表

题目: 题解: func dfs(node *Node) (last *Node) {cur : nodefor cur ! nil {next : cur.Next// 如果有子节点,那么首先处理子节点if cur.Child ! nil {childLast : dfs(cur.Child)next cur.Next// 将 node 与 child 相连cur.Next cur.Chi…

遗传算法与深度学习实战(14)——进化策略详解与实现

遗传算法与深度学习实战(14)——进化策略详解与实现 0. 前言1. 进化策略1.1 进化策略原理1.2 将进化策略应用于函数逼近 2. 实现进化策略小结系列链接 0. 前言 进化策略 (Evolutionary Strategies, ES) 是进化计算和遗传方法的扩展,增加了控…

【Python学习手册(第四版)】学习笔记24-高级模块话题

个人总结难免疏漏,请多包涵。更多内容请查看原文。本文以及学习笔记系列仅用于个人学习、研究交流。 本来计划中秋发布几篇文章,结果阳了,发烧、头疼、咽疼,修养了近一周,还没好完。希望大家都能有个好身体&#xff0…