不太一样的Go Web框架—编程范式
项目地址:https://github.com/Codexiaoyi/linweb
这是一个系列文章:
前言
上文说过,linweb不追求性能,相比而言注重编程范式。本人也是dotneter,个人觉得.net那种注解定义路由的方式更为舒服,并且接口文件统一规定在Controller文件夹下,以 XxxController 命名。
当然,在Go中也是可以实现这样的方式,但是将用到大量反射,所以势必会降低性能,所以说"不太一样的Web框架"。
基本范式
所谓编程范式,也就是你的框架定义规范,使用用户按照你的规范写逻辑业务。
路由
路由解析是一个web框架不可避免的模块,我们看gin是如何定义路由的。
func main() {
router := gin.Default()
// Simple group: v1
v1 := router.Group("/v1")
{
v1.POST("/login", loginEndpoint)
v1.POST("/submit", submitEndpoint)
v1.POST("/read", readEndpoint)
}
// Simple group: v2
v2 := router.Group("/v2")
{
v2.POST("/login", loginEndpoint)
v2.POST("/submit", submitEndpoint)
v2.POST("/read", readEndpoint)
}
router.Run(":8080")
}
在应用gin的时候,我们通常会将路由定义与接口方法对应写在一起,统一管理,这样管理方便,也是Go的web框架多数采用的方式。
相比之下,linweb更希望路由定义和方法放在一起,然后以定义Controller的方式,路由地址更加直观。
package controllers
import (
"github.com/Codexiaoyi/linweb/interfaces"
)
type BlogController struct {
}
//[GET("/blog/:id")]
func (blog *BlogController) GetBlog(c interfaces.IContext) {
}
在根目录下创建一个 controllers 文件夹,所有的api都定义在controllers包中。根据不同的 controller 名称区分文件。
自定义插件
linweb中所有功能与主流程间的依赖都是解耦的,所有实现都面向接口,完全遵守依赖倒置原则。
要实现这样的方式也不难:
- 定义一套接口,使得实现相应接口的结构体都可以运行在linweb中。
- 完成默认实现,默认应用默认实现在linweb中。
- 开放传入自定义插件实现的方法。
代码实现
在Go语言框架中大量使用Option模式实现上述的需求(完整代码详见github)。
1.首先我们定义一个自定义插件类型,并写一个默认的插件函数。
//自定义插件类型,返回可以传入Linweb的函数
type CustomizePlugins func(lin *Linweb)
func defaultPlugins() CustomizePlugins {
return func(lin *Linweb) {
lin.markRouter = router.New()
lin.markContext = &context.Context{}
lin.markMiddleware = &middleware.Middleware{}
lin.markInject = injector.Instance()
lin.markCache = cache.Instance()
lin.markModel = &model.Model{}
}
}
2.定义各个插件模块对应的快捷入口函数。
// Customize router plugin.这里参数传入自定义的Router实现
func RouterPlugin(router interfaces.IRouter) CustomizePlugins {
return func(lin *Linweb) {
lin.markRouter = router
}
}
// Customize context plugin.
func ContextPlugin(context interfaces.IContext) CustomizePlugins {
return func(lin *Linweb) {
lin.markContext = context
}
}
......
3.在linweb包的New初始化函数中,传入用户自定义的CustomizePlugins。
// Create a new Linweb.
// Add customize plugins with method of plugins.go, otherwise use default plugins.
func NewLinweb(plugins ...CustomizePlugins) *Linweb {
lin := &Linweb{}
//应用默认插件
defaultPlugins()(lin)
//根据传入的用户自定义插件覆盖默认插件
for _, plugin := range plugins {
plugin(lin)
}
pluginsModel = lin.markModel
Cache = lin.markCache
return lin
}
如何应用
在linweb项目中的linweb_test.go中,用到了mock框架(后续测试部分会介绍)模拟接口实现:
// Arrange:mock data
ctrl := gomock.NewController(t)
defer ctrl.Finish()
// mock a new context instance
mock_context := mocks.NewMockIContext(ctrl)
//Act
linweb := NewLinweb(ContextPlugin(mock_context))
如代码所见,我们调用linweb的ContextPlugin函数传入自定义插件,再将返回值传入NewLinweb初始化函数中。
总结
本文,介绍了linweb的基本的编程范式,也实现了自定义插件功能。
接下来,我们需要根据前文说的功能逐步添加到linweb中。
不太一样的Go Web框架—编程范式的更多相关文章
- 从零构建一个简单的 Python Web框架
为什么你想要自己构建一个 web 框架呢?我想,原因有以下几点: 你有一个新奇的想法,觉得将会取代其他的框架 你想要获得一些名气 你遇到的问题很独特,以至于现有的框架不太合适 你对 web 框架是如何 ...
- Python高级网络编程系列之终极篇---自己实现一个Web框架
通过前面几个小节的学习,现在我们想要把之前学到的知识点给串联起来,实现一个很小型的Web框架.虽然很小,但是用到的知识点都是比较多的.如Socket编程,装饰器传参在实际项目中如何使用.通过这一节的学 ...
- Python编程Web框架 :Django 从入门到精通
Django是一个高级别的Python Web框架,它鼓励快速开发和干净实用的设计. 现在我们开始学习它. Django学习之 第一章:Django介绍 Django学习之 第二章:Django快速上 ...
- 两个Python web框架:Django & Tornado比较
就是说它作为 web 框架比 Django 简单,又支援异步 IO,且更不需要前端的 webserver ? 我已经混乱了, Tornado是 Nginx.Django.Node.js 的结合体?又或 ...
- 蜗牛历险记(二) Web框架(中)
上篇简单介绍了框架所使用的Autofac,采用Autofac提供的Ioc管理整个Web项目中所有对象的生命周期,实现框架面向接口编程.接下来介绍框架的日志系统. 一.介绍之前 框架日志是否有存在的必要 ...
- dotweb——go语言的一个微型web框架(一)
dotweb是16年正式托管到github的一个开源项目,go语言的web框架目前也有很多,出名的有bee和echo.它们都是很优秀的框架,但是我们喜欢更轻.更小的东西,经历一些之后我们更青睐微服务这 ...
- 利用python web框架django实现py-faster-rcnn demo实例
操作系统.编程环境及其他: window7 cpu python2.7 pycharm5.0 django1.8x 说明:本blog是上一篇blog(http://www.cnblogs.co ...
- 【Flask】微型web框架flask大概介绍
Flask Flask是一个基于python的,微型web框架.之所以被称为微型是因为其核心非常简单,同时具有很强的扩展能力.它几乎不给使用者做任何技术决定. 安装flask时应该注意其必须的几个支持 ...
- web框架。Django--
一,DIY一个web框架 1.1什么是web框架 1.2用socket模拟B-S的服务端 1.3,浏览器端的network查看 1.4,request格式 1.5,response格式 1.6,初识w ...
随机推荐
- OpenCV使用级联分类器实现人脸检测
一.概述 案例:使用opencv级联分类器CascadeClassifier+其提供的特征数据实现人脸检测,检测到人脸后使用红框画出来. API介绍:detectMultiScale( InputAr ...
- _u32定义
驱动开发的原则: 能用__u32就最好用它,或者用u_int32_t之类的也可以,但不要直接用unsigned int等默认的数据类型.目的是让别人明白,你这个变量占多大内存. 原因: 1.你不能确定 ...
- springcloud学习00-开发工具相关准备
用maven构建springcloud项目,目录结构(图片来源:https://blog.csdn.net/qq_36688143/article/details/82755492) 1.maven ...
- Ls 命令执行什么功能?可以带哪些参数,有什么区别?
ls 执行的功能:列出指定目录中的目录,以及文件 哪些参数以及区别:a 所有文件 l 详细信息,包括大小字节数,可读可写可执行的权限等
- Spring源码分析笔记--AOP
核心类&方法 BeanDefinition Bean的定义信息,封装bean的基本信息,从中可以获取类名.是否是单例.是否被注入到其他bean中.是否懒加载.bean依赖的bean的名称等. ...
- 如何基于 ZEGO SDK 实现 Android 一对一音视频聊天应用
疫情期间,很多线下活动转为线上举行,实时音视频的需求剧增,在视频会议,在线教育,电商购物等众多场景成了"生活新常态". 本文将教你如何通过即构ZEGO sdk在Android端搭建 ...
- 程序人生:织梦dedecms后台/会员验证码关闭
dedecms默认是所有的功能几乎只要用到验证码的地方我们都需要验证的,如果要关闭一些验证功能我们可以参考下面的教程,这里介绍了关闭后台,留言板,会员系统等验证码功能关闭了.提示:支持DedeCMS ...
- 【Web Audio API】 — 那些年的 web audio
转 TAT.Jdo:[Web Audio API] - 那些年的 web audio 这主题主要是早期对 web audio api的一些尝试,这里整理一下以便以后翻阅,如有错误,诚请指正. 在这之前 ...
- mysql获取表的列名
DESC test4 SHOW COLUMNS FROM test4 SELECT COLUMN_NAME FROM information_schema.columns WHERE table_n ...
- Linux环境下Eclipse中快捷键不起作用
在window->Preferences->general->keys中, 找到 content asist 修改下边值 Binding 改成 Alt+/ When 改为 Editi ...