不太一样的Go Web框架—编程范式

项目地址:

这是一个系列文章:前言

如上所述,我们不追求性能,而是专注于编程范式。我个人也觉得.net注解方式定义路由更舒服,接口文件统一指定在文件夹下,以.命名。

当然,这种方法在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框架使用的方式。

相比之下,更希望将路由定义和方法放在一起,然后更直观地定义路由地址。

package controllers
import (
	"github.com/Codexiaoyi/linweb/interfaces"
)
type BlogController struct {
}
//[GET("/blog/:id")]
func (blog *BlogController) GetBlog(c interfaces.IContext) {
}

在根目录下创建一个文件夹,所有API都在包中定义。文件以不同的名称区分。

自定义插件

中所有函数与主进程的依赖关系

是解耦的,所有的实现都是面向接口的,完全符合依赖倒置的原则。

这样实现并不难:

代码实现

Go语言框架中使用了大量的模式来实现上述需求(详见完整代码)。

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.在包的New初始化函数中,传入用户自定义的。

如何申请

在项目的.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))

在代码中可以看到,我们调用的函数传入自定义插件,然后返回值传入初始化函数。

总结

本文介绍了基本的编程范式,也实现了自定义插件功能。

接下来,我们需要根据上面提到的功能,逐步添加进去。

© 版权声明
THE END
喜欢就支持一下吧
点赞9赞赏 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容