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
}
相关推荐
Ai 编码助手1 小时前
在 Go 语言中如何高效地处理集合
开发语言·后端·golang
小丁爱养花2 小时前
Spring MVC:HTTP 请求的参数传递2.0
java·后端·spring
等一场春雨2 小时前
Java设计模式 九 桥接模式 (Bridge Pattern)
java·设计模式·桥接模式
Channing Lewis2 小时前
什么是 Flask 的蓝图(Blueprint)
后端·python·flask
轩辕烨瑾3 小时前
C#语言的区块链
开发语言·后端·golang
栗豆包5 小时前
w175基于springboot的图书管理系统的设计与实现
java·spring boot·后端·spring·tomcat
等一场春雨5 小时前
Java设计模式 十四 行为型模式 (Behavioral Patterns)
java·开发语言·设计模式
萧若岚6 小时前
Elixir语言的Web开发
开发语言·后端·golang
Channing Lewis6 小时前
flask实现重启后需要重新输入用户名而避免浏览器使用之前已经记录的用户名
后端·python·flask
Channing Lewis6 小时前
如何在 Flask 中实现用户认证?
后端·python·flask