func UnaryServerInterceptor() grpc.UnaryServerInterceptor {
	return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (res interface{}, err error) {
		var middleware []UnaryHandlerMiddleware
		for _, filter := range createFilters(info.FullMethod) {
			val, ok := unaryHooks.Load(filter)
			if !ok {
				continue
			}
			hooks := val.(*hooks)
			hooks.mu.Lock()
			for _, hook := range hooks.list {
				middleware = append(middleware, hook.f.(UnaryHandlerMiddleware))
			}
			hooks.mu.Unlock()
		}
		for i := len(middleware) - 1; i >= 0; i-- {
			handler = middleware[i](handler)
		}
		return handler(ctx, req)
	}
}
UnaryServerInterceptor returns a new unary server interceptor that executes registered hooks.
package hooks
import (
	"context"
	"strings"
	"sync"
	"google.golang.org/grpc"
)
type UnaryHandlerMiddleware func(grpc.UnaryHandler) grpc.UnaryHandler
type StreamHandlerMiddleware func(grpc.StreamHandler) grpc.StreamHandler
var unaryHooks sync.Map
var streamHooks sync.Map
type hooks struct {
	mu   sync.Mutex
	list []struct {
		name string
		f    interface{}
	}
}
func registerHook(hooksMap *sync.Map, filter, name string, f interface{}) {
	val, _ := hooksMap.LoadOrStore(filter, &hooks{})
	hooks := val.(*hooks)
	hooks.mu.Lock()
	defer hooks.mu.Unlock()
	for i := 0; i < len(hooks.list); i++ {
		if hooks.list[i].name == name {
			hooks.list[i].f = f
			return
		}
	}
	hooks.list = append(hooks.list, struct {
		name string
		f    interface{}
	}{name, f})
}
func unregisterHook(hooksMap *sync.Map, filter, name string) bool {
	val, ok := hooksMap.Load(filter)
	if !ok {
		return false
	}
	hooks := val.(*hooks)
	hooks.mu.Lock()
	defer hooks.mu.Unlock()
	for i := 0; i < len(hooks.list); i++ {
		if hooks.list[i].name == name {
			hooks.list = append(hooks.list[:i], hooks.list[i+1:]...)
			return true
		}
	}
	return false
}
func RegisterUnaryHook(filter, name string, f UnaryHandlerMiddleware) {
	registerHook(&unaryHooks, filter, name, f)
}
func UnregisterUnaryHook(filter, name string) bool {
	return unregisterHook(&unaryHooks, filter, name)
}
func RegisterStreamHook(filter, name string, f StreamHandlerMiddleware) {
	registerHook(&streamHooks, filter, name, f)
}
func UnregisterStreamHook(filter, name string) bool {
	return unregisterHook(&streamHooks, filter, name)
}
func createFilters(fullMethod string) []string {
	service := strings.SplitN(fullMethod[1:], "/", 2)[0]
	return []string{"/" + service, fullMethod}
}