Go语言简洁框架目录和高效的快发框架设计

前言

一个语言是否好友除了语言语法及内置包以外,还需要有一个设计不错框架,我们认为好的框架目录是一定是简洁的,目录结构都不能合理设计,那我们也不敢相信他能把框架设计的好。一个简洁的框架是可以让框架易学,让新人的快速上手。不论您公司人员流动如何,一定有新人加入,当一个新人拿到框架,如果能让他快速上手,肯定是能给您公司减少成本的。说了这么希望我们能达成框架目录结构的简洁理念,接下来我们一起看看我们设计简洁目录的框架咯。

框架目录

先看看框架目录:

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

 从目录总我们看到这个目录很简洁,这里的简洁不是为了简单而简单,而是在实用基础上进行精简。

框架设计中我们把框架的核心代码放在utils中,在项目开发中在非必要情况下不要去改动utils目录下的代码,业务代码放在app目录下,静态资源分别放在devsource和resource中(为什么分两个目录呢,这是因为方便部署直接拷贝resource目录带部署环境中,devsource是开始时用到资源到在生产环境中用不到,所以分开可以减少部署时上传资源)。目录结构中我们只要3个类型目录:一个框架核心代码目录、一个开发业务目录、一个静态资源目录。大道至简,开发时技术员只需在app目录下编写代码即可,不会把框架代码和业务代码混合在一起。

 接下来在看看app业务开发目录,这是开发时核心目录,也需要简洁。首先app目录下有个controller.go控制器文件,他是用来引入同目录文件目录,这是框架设计自动生成请求路径用到的。也就是说这个框架不需开发者开发一个接口手动添加一个请求路由,框架会会根据目录层级生成路由。

应用控制器

app下面的应该控制器代码如下:

package controller/**
* app路由引入口《引入模块控制器》
*/
import ("gofly/app/admin""gofly/app/business"_ "gofly/app/common""gofly/utils/gf"
)// 路由中间件/路由钩子
func RouterHandler(c *gf.GinCtx) {business.RouterHandler(c, "business")admin.RouterHandler(c, "admin")
}

再看app下的admin和business 这两个是框架的两个后台的后端,如果开发时业务不需有多租户我们就删除admin,这样app目录下就只剩下business和common了。所以说这个框架很简洁,也容易扩展多个端再加个目录即可。

模块目录

在继续看模块(即app下面目录)目录下的目录结构,这里就直接用business模块举例子了,选是system展开说明:

├── developer          # 开发者工具
├── datacenter         # 数据中心-数据字典-配置
├── user               # 用户登录等操作
├── system             # 后台系统管理(展开举例)
│   ├── account.go     # 用户管理
│   ├── dept.go        # 部门管理
│   ├── log.go         # 系统日志
│   ├── role.go        # 角色管理
│   └── rule.go        # 系统菜单
│
├── createcode         # 代码生成示例代码 
│   ├── product.go     # 演示产品
│   └── productcate.go # 演示产品分类
│
└── controller.go      # 模块控制器-也就是business这个模块的控制   

模块控制器

模块下的控制器代码如下:

package business/**
* 引入控制器-文件夹名称的路径
*/
import (_ "gofly/app/business/datacenter"_ "gofly/app/business/developer"_ "gofly/app/business/system"_ "gofly/app/business/user""gofly/utils/gf"
)// 路由中间件/路由钩子,noAuths无需路由验证接口,可以从c获取请求各种参数
func RouterHandler(c *gf.GinCtx, modelname string) {if gf.IsModelPath(c.FullPath(), modelname) { //在这里面处理拦截操作,如果需要拦截终止执行则:c.Abort()// 判断请求接口是否需要验证权限(RBAC的权限)if gf.NeedAuthMatch(c) {haseauth := gf.CheckAuth(c, modelname)if haseauth {c.Next()} else {gf.Failed().SetMsg(gf.LocaleMsg().SetLanguage(c.Request.Header.Get("locale")).Message("sys_auth_permission")).SetData(haseauth).Regin(c)c.Abort()}} else {c.Next()}}
}

接口代码实现

在看看如下编写接口代码,我们用createcode这个代码示例类举例,首先创建一个product.go,然后创建增删改查的接口,示例代码如下:

package createcodeimport ("gofly/utils/gf""gofly/utils/tools/gmap"
)// 演示代码-产品管理
type Product struct{}func init() {fpath := Product{}gf.Register(&fpath, fpath)
}// 获取列表
func (api *Product) GetList(c *gf.GinCtx) {pageNo := gf.Int(c.DefaultQuery("page", "1"))pageSize := gf.Int(c.DefaultQuery("pageSize", "10"))//搜索添条件param, _ := gf.RequestParam(c)whereMap := gmap.New()whereMap.Set("business_id", c.GetInt64("businessID"))if cid, ok := param["cid"]; ok && gf.Int(cid) != 0 {cids := gf.CateAllChilId("createcode_product_cate", cid)whereMap.Set("cid In(?)", cids)}if title, ok := param["title"]; ok && title != "" {whereMap.Set("title like ?", "%"+gf.String(title)+"%")}if status, ok := param["status"]; ok && status != "" {whereMap.Set("status", status)}if createtime, ok := param["createtime"]; ok && createtime != "" {datetime_arr := gf.SplitAndStr(gf.String(createtime), ",")whereMap.Set("createtime between ? and ?", gf.Slice{datetime_arr[0] + " 00:00", datetime_arr[1] + " 23:59"})}if userType, ok := param["userType"]; ok && userType != "" {whereMap.Set("userType", userType)}MDB := gf.Model("createcode_product").Where(whereMap)totalCount, _ := MDB.Clone().Count()list, err := MDB.Fields("id,title,image,cid,userType,images,likeColor,record_audio,price,des,sex,workerway,status,updatetime").Page(pageNo, pageSize).Order("id desc").Select()if err != nil {gf.Failed().SetMsg(err.Error()).Regin(c)} else {for _, val := range list {val["cidName"] = gf.GetTalbeFieldVal("createcode_product_cate", "name", val["cid"])val["userType"] = gf.GetDicFieldVal("2", val["userType"])if val["workerway"].String() != "" {val["workerway"] = gf.VarNew(gf.SplitAndStr(val["workerway"].String(), ","))}}gf.Success().SetMsg("获取全部列表").SetData(gf.Map{"page":     pageNo,"pageSize": pageSize,"total":    totalCount,"items":    list}).Regin(c)}
}// 保存
func (api *Product) Save(c *gf.GinCtx) {param, _ := gf.RequestParam(c)var f_id = gf.GetEditId(param["id"])param["workerway"] = gf.ArrayToStr(param["workerway"], ",")if f_id == 0 {param["business_id"] = c.GetInt64("businessID") //当前用户商户IDaddId, err := gf.Model("createcode_product").Data(param).InsertAndGetId()if err != nil {gf.Failed().SetMsg("添加失败").SetData(err).Regin(c)} else {if addId != 0 {gf.Model("createcode_product").Where("id", addId).Update(gf.Map{"weigh": addId})}gf.Success().SetMsg("添加成功!").SetData(addId).Regin(c)}} else {res, err := gf.Model("createcode_product").Where("business_id", c.GetInt64("businessID")).Where("id", f_id).Update(param)if err != nil {gf.Failed().SetMsg("更新失败").SetData(err).Regin(c)} else {gf.Success().SetMsg("更新成功!").SetData(res).Regin(c)}}
}// 更新状态
func (api *Product) UpStatus(c *gf.GinCtx) {param, _ := gf.RequestParam(c)res, err := gf.Model("createcode_product").Where("business_id", c.GetInt64("businessID")).Where("id", param["id"]).Update(param)if err != nil {gf.Failed().SetMsg("更新失败!").SetData(err).Regin(c)} else {msg := "更新成功!"if res == nil {msg = "暂无数据更新"}gf.Success().SetMsg(msg).SetData(res).Regin(c)}
}// 删除
func (api *Product) Del(c *gf.GinCtx) {param, _ := gf.RequestParam(c)res, err := gf.Model("createcode_product").Where("business_id", c.GetInt64("businessID")).WhereIn("id", param["ids"]).Delete()if err != nil {gf.Failed().SetMsg("删除失败").SetData(err).Regin(c)} else {gf.Success().SetMsg("删除成功!").SetData(res).Regin(c)}
}// 获取内容
func (api *Product) GetContent(c *gf.GinCtx) {id := c.DefaultQuery("id", "")if id == "" {gf.Failed().SetMsg("请传参数id").Regin(c)} else {data, err := gf.Model("createcode_product").Where("business_id", c.GetInt64("businessID")).Where("id", id).Find()if err != nil {gf.Failed().SetMsg("获取内容失败").SetData(err).Regin(c)} else {if data != nil && data["workerway"].String() != "" {data["workerway"] = gf.VarNew(gf.SplitAndStr(data["workerway"].String(), ","))}gf.Success().SetMsg("获取内容成功!").SetData(data).Regin(c)}}
}

好了这就是框架设计结构与其编写业务代码流程,这里看看可以还是有点复杂,但在IED编辑器中就一目了然。

GoFly不仅是软件开发追求简单,嵌入式开发也最求简单,想学习Go语言嵌入式的可以去:嵌入式视频教程了解一下。

更多资料在:GoFly全栈开发社区 这里处理资料还可以交流学习的。

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

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

相关文章

【网络 MAC 学习专栏 -- 如何理解 PHY 的 Link Up】

请阅读【嵌入式开发学习必备专栏 Cache | MMU | AMBA BUS | CoreSight | Trace32 | CoreLink | ARM GCC | CSH】 文章目录 OverviewClause 22/Clause 45Clause 22Clause 45 PHY Link 状态的软件实现 转自: 开心果 Need Car 2022年10月20日 09:50 上海 Overview PHY…

慧集通(DataLinkX)iPaaS集成平台-系统管理之用户及权限

系统用户 通过左侧菜单栏【系统管理】→【用户及权限】→【系统用户】进入到系统用户维护的主界面,在该界面我们可以看到已经维护好的系统用户,以及一些关于系统用户的功能按钮,有新建、编辑、删除、停用、启用、解锁等。 新建:在…

【机器学习实战入门】基于深度学习的乳腺癌分类

什么是深度学习? 作为对机器学习的一种深入方法,深度学习受到了人类大脑和其生物神经网络的启发。它包括深层神经网络、递归神经网络、卷积神经网络和深度信念网络等架构,这些架构由多层组成,数据必须通过这些层才能最终产生输出。…

Spring Boot + Apache POI 实现 Excel 导出:BOM物料清单生成器(支持中文文件名、样式美化、数据合并)

目录 引言 Apache POI操作Excel的实用技巧 1.合并单元格操作 2.设置单元格样式 1. 创建样式对象 2. 设置边框 3. 设置底色 4. 设置对齐方式 5. 设置字体样式 6.设置自动换行 7. 应用样式到单元格 3. 定位和操作指定单元格 4.实现标签-值的形式 5.列宽设置 1. 设…

[每周一更]-(第132期):AI工具集对比

文章目录 1.问答互动类(31个)2.图像类**简要对比说明**: **总结**: 3.代码类WindsurfCursor AIGithub Copilot 4.大模型**AlphaFold 的独特性与优势****AlphaFold 的局限性****主要大模型对比** AI的核心目标是通过模拟人类智能来…

PortSwigger靶场练习---第二关-查找和利用未使用的 API 端点

第二关:Finding and exploiting an unused API endpoint 实验:查找和利用未使用的 API 端点 PortSwigger靶场地址: Dashboard | Web Security Academy - PortSwigger 题目: 官方提示: 在 Burp 的浏览器中&#xff0c…

python_在钉钉群@人员发送消息

python_在钉钉群人员发送消息 1、第一种 企业内部机器人群聊实现人接入指南,适用于群机器人接收消息,处理完一系列的动作之后,将消息返回给发消息的人员,同时该人员。 需要在企微后台新建一个自建应用,在自建应用里…

天机学堂5-XxlJobRedis

文章目录 梳理前面的实现:Feign点赞改进 day07-积分系统bitmap相关命令签到增加签到记录计算本月已连续签到的天数查询签到记录 积分表设计签到-->发送RabbitMQ消息,保存积分对应的消费者:**消费消息 用于保存积分**增加积分查询个人今日积…

【Block总结】Conv2Former的Block,结合卷积网络和Transformer的优点|即插即用

背景与动机 Conv2Former是一种新型的卷积神经网络(ConvNet),旨在结合卷积网络和Transformer的优点,以提升视觉识别任务的性能。传统的卷积神经网络在处理局部特征提取方面表现优异,但在建模全局信息和长距离依赖关系时…

智能化植物病害检测:使用深度学习与图像识别技术的应用

植物病害一直是农业生产中亟待解决的问题,它不仅会影响作物的产量和质量,还可能威胁到生态环境的稳定。随着人工智能(AI)技术的快速发展,尤其是深度学习和图像识别技术的应用,智能化植物病害检测已经成为一…

【TCP】rfc文档

tcp协议相关rfc有哪些 TCP(传输控制协议)是一个复杂的协议,其设计和实现涉及多个RFC文档。以下是一些与TCP协议密切相关的RFC文档列表,按照时间顺序排列,涵盖了从基础定义到高级特性和优化的各个方面: 基…

机器学习皮马印第安人糖尿病数据集预测报告

目录 1.项目选题与设计方案 1.1项目选题 1.2设计方案 2.功能实现 2.1 主要功能介绍 2.2 开发环境及平台介绍 2.3 实现过程 2.3.1数据分析 2.3.2算法设计 2.3.3 python代码 3.个人心得体会 1.项目选题与设计方案 1.1项目选题 我国的糖尿病患者初诊时约8&a…

HTML5+Canvas实现的鼠标跟随自定义发光线条源码

源码介绍 HTML5Canvas实现的鼠标跟随自定义发光线条特效源码非常炫酷&#xff0c;在黑色的背景中&#xff0c;鼠标滑过即产生彩色变换的发光线条效果&#xff0c;且线条周围散发出火花飞射四溅的粒子光点特效。 效果预览 源码如下 <!DOCTYPE html PUBLIC "-//W3C//D…

Dart语言

基础篇&#xff1a; 第 1 部分&#xff1a;Dart 的基础语法 1.1 Dart 程序的结构 一个简单的 Dart 程序通常包含一个 main() 函数&#xff0c;这是程序的入口点。所有 Dart 程序都会从 main() 函数开始执行。 void main() {print(Hello, Dart!); } void 表示 main() 函数没…

通过idea创建的springmvc工程需要的配置

在创建的spring mvc工程中&#xff0c;使用idea开发之前需要配置文件包括porm.xml、web.xml、springmvc.xml 1、porm.xml 工程以来的spring库&#xff0c;主要包括spring-aop、spring-web、spring-webmvc&#xff0c;示例配置如下&#xff1a; <project xmlns"http:/…

Ansible实战:如何正确选择 command 和shell模块?

在使用Ansible进行自动化运维时&#xff0c;command 和 shell 模块是我们执行命令的好帮手。虽然它们看起来很相似&#xff0c;但在功能特性和适用场景上其实有着明显的不同。正确选择合适的模块不仅能够提高任务的效率&#xff0c;还能帮助我们规避一些潜在的风险。在这篇文章…

【STM32-学习笔记-4-】PWM、输入捕获(PWMI)

文章目录 1、PWMPWM配置 2、输入捕获配置3、编码器 1、PWM PWM配置 配置时基单元配置输出比较单元配置输出PWM波的端口 #include "stm32f10x.h" // Device headervoid PWM_Init(void) { //**配置输出PWM波的端口**********************************…

学习微信小程序的下拉列表控件-picker

1、创建一个空白工程 2、index.wxml中写上picker布局&#xff1a; <!--index.wxml--> <view class"container"><picker mode"selector" range"{{array}}" bindchange"bindPickerChange"><view class"pick…

【神经网络基础】

目录 一、神经网络的构成 1.1什么是神经网络&#xff1f; 1.2 激活函数 1.2.1 Sigmoid 1.2.2 Tanh 1.2.3 ReLU 1.2.4 softmax 1.2.5 其他激活函数 1.2.6 选择激活函数 1.3 参数初始化 1.4 模型构建 二、损失函数 2.1 分类问题 2.1.1多分类&#xff08;多分类交叉…

STM32 学习笔记【补充】(十)硬件I2C读写MPU6050

该系列为笔者在学习STM32过程&#xff08;主线是江科大的视频&#xff09;中的记录与发散思考。 初学难免有所纰漏、错误&#xff0c;还望大家不吝指正&#xff0c;感谢~ 一、I2C 外设简介 I2C&#xff08;Inter-Integrated Circuit&#xff09;是一种多主多从的串行通信协议…