go实现函数递归栈(grpc拦截器)

package main

import (
	"context"
	"log"
)

func main() {

	_Handler(
		"hello",
		context.Background(),
		multi([]Interceptor{A, B}...),
	)
}

func A(ctx context.Context, req interface{}, handler Handler) (interface{}, error) {
	defer func() {
		log.Printf("call A() done")
	}()

	log.Printf("call A()")
	return handler(ctx, req)
}

func B(ctx context.Context, req interface{}, handler Handler) (interface{}, error) {
	defer func() {
		log.Printf("call B() done")
	}()

	log.Printf("call B()")
	return handler(ctx, req)
}

//------------------
type Handler = func(ctx context.Context, req interface{}) (interface{}, error)
type Interceptor = func(ctx context.Context, req interface{}, handler Handler) (interface{}, error)

func echo(ctx context.Context, req interface{}) (interface{}, error) {
	log.Println(req)
	return "ok", nil
}

func _Handler(req interface{}, ctx context.Context, inter Interceptor) (interface{}, error) {

	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return echo(ctx, req)
	}
	return inter(ctx, req, handler)
}

func multi(interceptors ...Interceptor) Interceptor {
	n := len(interceptors)

	return func(ctx context.Context, req interface{}, handler Handler) (interface{}, error) {
		chainer := func(currentInter Interceptor, currentHandler Handler) Handler {
			return func(currentCtx context.Context, currentReq interface{}) (interface{}, error) {
				return currentInter(currentCtx, currentReq, currentHandler)
			}
		}

		chainedHandler := handler
		for i := n - 1; i >= 0; i-- {
			chainedHandler = chainer(interceptors[i], chainedHandler)
		}

		return chainedHandler(ctx, req)
	}
}

grpc源码:

// Execution is done in left-to-right order, including passing of context.
// For example ChainUnaryServer(one, two, three) will execute one before two before three, and three
// will see context changes of one and two.
func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor {
	n := len(interceptors)

	return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
		chainer := func(currentInter grpc.UnaryServerInterceptor, currentHandler grpc.UnaryHandler) grpc.UnaryHandler {
			return func(currentCtx context.Context, currentReq interface{}) (interface{}, error) {
				return currentInter(currentCtx, currentReq, info, currentHandler)
			}
		}

		chainedHandler := handler
		for i := n - 1; i >= 0; i-- {
			chainedHandler = chainer(interceptors[i], chainedHandler)
		}

		return chainedHandler(ctx, req)
	}
}
// UnaryHandler defines the handler invoked by UnaryServerInterceptor to complete the normal
// execution of a unary RPC. If a UnaryHandler returns an error, it should be produced by the
// status package, or else gRPC will use codes.Unknown as the status code and err.Error() as
// the status message of the RPC.
type UnaryHandler func(ctx context.Context, req interface{}) (interface{}, error)

// UnaryServerInterceptor provides a hook to intercept the execution of a unary RPC on the server. info
// contains all the information of this RPC the interceptor can operate on. And handler is the wrapper
// of the service method implementation. It is the responsibility of the interceptor to invoke handler
// to complete the RPC.
type UnaryServerInterceptor func(ctx context.Context, req interface{}, info *UnaryServerInfo, handler UnaryHandler) (resp interface{}, err error)



func _xx_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
	in := new(EchoReq)
	if err := dec(in); err != nil {
		return nil, err
	}
	if interceptor == nil {
		return srv.(xx).xx(ctx, in)
	}
	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: "/xx.xx/xx",
	}
	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
		return srv.(xx).Echosvr(ctx, req.(*xx))
	}
	return interceptor(ctx, in, info, handler)
}
上一篇:[Java 学习笔记] 接口


下一篇:elementui树状结构添加右键点击事件