为了让Go开发变得更简单我把传统多层结构改为准单层
前言
自从使用上Go语言我们把开发简单贯彻到底,一个语言是否用得到舒服吗,我们一方面是看语言本身,另一方面还得有个好用框架,我们开发项目一般是不会从零开始编写代码,都是找个框架,在框架基础上搭建自己业务。所以我们一直想有一个满足开发简单、维护简单、学习简单、性能优秀、安全保障的框架,全网搜索没有找到合意框架,经过7年积累,自己戳一个,目前使用已经满足快速开发外包项目要求了,新老程序员交接成本也很低。本文我们一起分享一下我们这赖人搭建的框架。
框架设计思路
我们包传统常见的表现层(Controller),业务逻辑层(Service),和数据访问层(DAO),压缩为仅1层即业务逻辑层,简称接口实现层。但我们框架是存在Controller层的,但开发时我们不会去写Controller层,Controller框架作为约束规则会自己生产,我们仅编写当前请求操作接口代码即可。
结构如下:
├── app # 应用目录
│ ├── douyinapp # 抖音应用模块
│ │ ├── home # 应用首页数据
│ │ ├── user #抖音用户相关业务接口
│ │ └── controller.go # 模块控制器-仅针对douyinapp控制
│ └── controller.go # 总应用控制器
其中controller.go是控制,它控制使用模块,及模块控制它控制模块下的业务类使用。
控制层
1.主控控制代码如下,它是负责控制模块引入,也就是那个模块使用就在import引入,不用就去掉。
package controller
/**
* app路由引入口《引入模块控制器》
*
* 请把您使用包用 _ "gofly/app/xx"导入您编写的包 自动生成路由
* 不需要使用的模块则注释掉 例如home模块暂时用不到就注释掉,这样不占用资源,使用是取消注释即可。
* 路由规则:包路径“business/article” + 包中结构体“Cate”转小写+方法名(首字母转小写_ "gofly/app/business"
* 有控制的模块请在RouterHandler添加模块的路由钩子
*/
import (
"gofly/app/douyinapp"
"gofly/utils/gf"
)
// 路由中间件/路由钩子
func RouterHandler(c *gf.GinCtx) {
douyinapp.RouterHandler(c, gf.IsModelPath(c.FullPath(), "douyinapp"))
}
2.模块控制器代码如下,它是负责控制业务类引入,也就是那个业务类使用就在import引入,不用就去掉。
package douyinapp
/**
* 引入控制器
* 请把您使用包用 _ "gofly/app/home/XX"导入您编写的包 自动生成路由
* 不是使用则注释掉
* 路由规则:包路径“home/article” + 包中结构体“Cate”转小写+方法名
*/
import (
_ "gofly/app/douyinapp/home"
_ "gofly/app/douyinapp/user"
"gofly/utils/gf"
)
// 路由中间件/路由钩子,可以从c获取请求各种参数
func RouterHandler(c *gf.GinCtx, IsCtr bool) {
if IsCtr {
c.Next()
}
}
接口实现层(业务逻辑层)代码实现
我们在接口实现层中编写,业务代码,在开发时我们只关心接口层,其他框架帮大家生成或自动引入无需人为编写,我们仅仅编写接口实现层代码,下面演示接口实现层代码编写步骤:
如下图,是home接口实现层代码,我们开发时就在douyinapp模块目录下添加业务类目录,然后在douyinapp目录的controller.go控制器import业务类,代码生成会自动引入。手动添加要自己用途一下。
1.添加业务类目录
如上图我们在douyinapp模块创建首页home类,我们直接创建名称为home文件夹即可
2.创建接口文件
创建接口有两种一种是接口忽略文件层路由则命名为index.go,生成路由/douyinapp/接口名。另一个是用文件名作为一层路由名称则命名:文件(字母或者字母+数字).go,这样生成路由为 /douyinapp/文件名/接口名。
以一种为例,我们创建index.go文件,添加一个获取首页轮播图数据,代码如下:
package home
import "gofly/utils/gf"
/**
* 首页功能接口
*/
type Index struct{}
func init() {
fpath := Index{}
gf.Register(&fpath, fpath)
}
// 获取Swipe轮播数据
func (api *Index) GetSwipe(c *gf.GinCtx) {
list := gf.List{gf.Map{"name": "第一页", "image": "https://weui.shanliwawa.top/weui/images/1.jpg"}, gf.Map{"name": "第2页", "image": "https://weui.shanliwawa.top/weui/images/2.jpg"}}
gf.Success().SetMsg("获取Swipe轮播数据").SetData(list).Regin(c)
}
这样我们就编写好一个getSwipe接口,请求路由为:/douyinapp/home/getSwipe,如下图是框架自动生成路由,在终端打印日志。
总结
从上面我们可以看出编写一个接口很简单,代码很少,开发是我们也只关心业务接口,不用去几个文件编写代码,需要多个文件跳来跳去的。
如果你需要数据库操作,参考如下代码,直接在接口层编写,不用再写model层。
// 更新状态
func (api *Product) UpStatus(c *gf.GinCtx) {
param, _ := gf.RequestParam(c)
res2, err := gf.Model("createcode_product").Where("id", param["id"]).Data(gf.Map{"status": param["status"]}).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 *Product) Del(c *gf.GinCtx) {
param, _ := gf.RequestParam(c)
res2, err := gf.Model("createcode_product").WhereIn("id", param["ids"]).Delete()
if err != nil {
gf.Failed().SetMsg("删除失败").SetData(err).Regin(c)
} else {
gf.Success().SetMsg("删除成功!").SetData(res2).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("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)
}
}
}
感兴趣的朋友前往社区获取代码,有开源免费版和企业版根据情况自行选择:
goflys.cn/home
注意:框架有开源免费和企业版,企业版收费,如果想白嫖企业版的不建议去了解,谢谢,我们只分享给需要开发者。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: