code: func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor {
  	n := len(interceptors)
  
  	if n > 1 {
  		lastI := n - 1
  		return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
  			var (
  				chainHandler grpc.UnaryHandler
  				curI         int
  			)
  
  			chainHandler = func(currentCtx context.Context, currentReq interface{}) (interface{}, error) {
  				if curI == lastI {
  					return handler(currentCtx, currentReq)
  				}
  				curI++
  				resp, err := interceptors[curI](currentCtx, currentReq, info, chainHandler)
  				curI--
  				return resp, err
  			}
  
  			return interceptors[0](ctx, req, info, chainHandler)
  		}
  	}
  
  	if n == 1 {
  		return interceptors[0]
  	}
  
  	// n == 0; Dummy interceptor maintained for backward compatibility to avoid returning nil.
  	return func(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
  		return handler(ctx, req)
  	}
  }
docs: // ChainUnaryServer creates a single interceptor out of a chain of many interceptors.
  //
  // 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.