Golang中可以通过定义一个函数类型,并且在函数类型上定义方法,满足该函数类型签名的函数可以转换为该函数类型,并且调用函数类型实现的方法,有些框架的中间件就是通过这种方式实现的,比如下面这段代码:

package main

import (
	"context"
	"fmt"
)

type HandlerFunc func(*context.Context)

func (f HandlerFunc) Work(ctx *context.Context) {
	f(ctx)
}

func Outer(next HandlerFunc) {
	ctx := context.WithValue(context.Background(), "key1", "value1")
	next.Work(&ctx)
}

func Inner(ctx *context.Context) {
	logstr := fmt.Sprintf("i am inner, the value is: %s", (*ctx).Value("key1"))
	fmt.Println(logstr)
}

func main() {
	inner := HandlerFunc(Inner)
	Outer(inner)
}

复制代码

Inner是实际的业务处理函数,Outer实现为中间件接收HandlerFunc类型的函数作为参数,然后在中间件逻辑之后,调用next.Work()处理业务逻辑。
直接将函数作为参数传递也能实现中间件的原理,比如:

package main

import (
	"context"
	"fmt"
)

func Outer(next func(*context.Context)) {
	ctx := context.WithValue(context.Background(), "key1", "value1")
	next(&ctx)
}

func Inner(ctx *context.Context) {
	logstr := fmt.Sprintf("i am inner, the value is: %s", (*ctx).Value("key1"))
	fmt.Println(logstr)
}

func main() {
	Outer(Inner)
}

复制代码