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)
}