golang 泛型 middleware 设计模式: 一次只做一件事

golang 泛型 middleware 设计模式: 一次只做一件事

1. 前言

本文主要介绍 在使用 gRPC 和 Gin 框架中常用的 middleware 设计模式

还有几种叫法

  1. 装饰器模式
  2. Pipeline 模式

设计思想:

  1. 10 个 10 行函数, 而不是 1 个 100 行函数
  2. 一次只做一件事, 而不一次做多件事
  3. 单一职责

2. 代码

已生产环境中大量使用, 每日执行千万次

go 复制代码
package chain

type Ctx[T any] struct {
	in  T // 数据入参
	fns []func(c *Ctx[T], in T) (err error)
	idx int
}

func NewCtx[T any](in T) *Ctx[T] {
	return &Ctx[T]{
		in:  in,
		idx: -1,
	}
}

func (c *Ctx[T]) Next() (err error) {
	c.idx++
	for ; c.idx < len(c.fns); c.idx++ {
		err = c.fns[c.idx](c, c.in)
		if err != nil {
			return
		}
	}
	return
}

func (c *Ctx[T]) Add(fns ...func(c *Ctx[T], in T) (err error)) {
	c.fns = append(c.fns, fns...)
}

3. test case

go 复制代码
package chain

import (
	"fmt"
	"testing"
	"time"
)

type Input struct {
	a int
}

func TestNewCtx(t *testing.T) {

	// 初始化
	in := Input{a: 1}
	c := NewCtx(&in)

	// 添加中间件
	c.Add(ctx1_cost)    // 记录耗时
	c.Add(ctx2_add)     // 数据加工
	c.Add(ctx3_product) // 数据加工2

	// 执行
	err := c.Next()
	if err != nil {
		panic(err)
	}

	// 检查结果
	fmt.Println(in.a)
	if in.a != 4 {
		panic(fmt.Sprintf("expect 4, but got %d", in.a))
	}
}

func ctx1_cost(c *Ctx[*Input], in *Input) (err error) {
	start := time.Now()
	defer func() {
		cost := time.Since(start)
		fmt.Println("cost:", cost)
	}()

	err = c.Next()
	return
}

func ctx2_add(c *Ctx[*Input], in *Input) (err error) {
	in.a += 1
	return
}

func ctx3_product(c *Ctx[*Input], in *Input) (err error) {
	in.a *= 2
	return
}
相关推荐
baozhengw7 分钟前
IntelliJ+SpringBoot项目实战(四)--快速上手数据库开发
spring boot·后端·数据库开发
颜淡慕潇12 分钟前
【数据库系列】 Spring Boot 集成 Neo4j 的详细介绍
java·数据库·spring boot·后端·neo4j
许野平27 分钟前
Rust:GUI 开源框架
开发语言·后端·rust·gui
刘翔在线犯法34 分钟前
Scala的迭代器
开发语言·后端·scala
无敌小肥00737 分钟前
Springboot 整合 itext 实现PDF文件合并,识别图片则转成PDF拼接
spring boot·后端·pdf
树不懒1 小时前
【设计模式】关联关系与依赖关系
设计模式
随心............1 小时前
python设计模式
java·开发语言·设计模式
IT大玩客2 小时前
SpringBoot如何集成WebSocket
spring boot·后端·websocket
ModelBulider2 小时前
九、HttpMessageConverter
java·开发语言·后端·spring·springmvc
就叫飞六吧2 小时前
电商系统表的1-n如何设计?情景分析
java·后端·spring