ZBIGBEAR / middleware

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

插件的实现方式

经常看到一些框架有插件,具体插件怎么实现的呢?这几天review同事代码的时候,发现他写了一段从消息队列中获取并处理消息的代码,其中用到了插件。真正保存消息之前的一些操作,比如耗时统计、参数处理、日志处理、异常捕获等操作都以插件的形式实现。这段代码让我学习到了插件实现的原理。方案一是对这段代码的实现。

这里还总结了一下gin框架的中间件实现方式,是一种顺序实现,它把中间件封装到自定义的Context结构体中,通过ctx.Next()实现链式调用。方案二是对这段代码的实现。

还有一种链式调用中间件,它的入参是next,返回值也是一个next,实现链式调用。这种函数套函数的用法不是很美观,同时也不具备什么可读性。方案三是这个方案的实现。

方案四是for循环方式实现middleware

示例

package main

import (
	"context"
	"fmt"

	"middleware/middleware"
	middlewarecontext "middleware/middleware_context"
)

func HandlerMsg(ctx context.Context, msg string) error {
	fmt.Println("HandlerMsg:", msg)
	return nil
}

func main() {
	// 方案一
	fmt.Println("===方案一 begin")
	m1 := middleware.NewMiddlewareManager(HandlerMsg)
	m1.Register(middleware.TimeCostMW, middleware.FilterMW, middleware.LoggerMW)
	if err := m1.Exec(context.Background(), "hello chain"); err != nil {
		panic(err)
	}
	fmt.Println("===方案一 end")

	// 方案二
	fmt.Println("===方案二 begin")
	m2 := middlewarecontext.NewMyContext()
	m2.Register(
		middlewarecontext.TimeCostMW,
		middlewarecontext.FilterMW,
		middlewarecontext.LoggerMW)
	if err := m2.Exec(); err != nil {
		panic(err)
	}
	fmt.Println("===方案二 end")

	// 方案三
	fmt.Println("===方案三 begin")
	ctx := context.Background()
	m3 := middlewarechain.TimeCostMW(ctx, func(ctx context.Context) error {
		PrintMsg("test")
		return nil
	})
	m4 := middlewarechain.FilterMW(ctx, m3)
	m5 := middlewarechain.LoggerMW(ctx, m4)
	if err := m5(ctx); err != nil {
		fmt.Println(err)
	}
	fmt.Println("===方案三 end")

	// 方案四
	fmt.Println("===方案四 begin")
	ctx = context.Background()
	middleware4 := middlewarefor.NewMiddlewareManager(
		middlewarefor.RecoveryMW,
		middlewarefor.LoggerMW,
		middlewarefor.TimeCostMW,
	)

	middleware4.Exec(ctx)
	fmt.Println("===方案四 end")
}

func PrintMsg(msg string) {
	fmt.Println("PrintMsg:" + msg)
}

结果

===方案一 begin
TimeCost before
FinlterMW begin
LoggerMW before 
HandlerMsg: hello chain
LoggerMW end 
FinlterMW end
TimeCostMW:cost 1000284305
===方案一 end
===方案二 begin
TimeCost before
FinlterMW begin
LoggerMW before 
LoggerMW end 
FinlterMW end
TimeCostMW:cost 1000699792
===方案二 end
===方案三 begin
LoggerMW before 
FinlterMW begin
TimeCost before
PrintMsg:test
TimeCostMW:cost 6045
FinlterMW end
LoggerMW end 
===方案三 end
===方案四 begin
2023/01/15 15:27:09 [RecoveryMW] befor
2023/01/15 15:27:09 [LoggerMW] befor
2023/01/15 15:27:09 [TimeCostMW] cost:0.000000s
2023/01/15 15:27:09 [LoggerMW] end
2023/01/15 15:27:09 [RecoveryMW] end
===方案四 end

About


Languages

Language:Go 100.0%