1. // chainUnaryClientInterceptors chains all unary client interceptors into one.
  2. func chainUnaryClientInterceptors(cc *ClientConn) {
  3. interceptors := cc.dopts.chainUnaryInts
  4. // Prepend dopts.unaryInt to the chaining interceptors if it exists, since unaryInt will
  5. // be executed before any other chained interceptors.
  6. if cc.dopts.unaryInt != nil {
  7. interceptors = append([]UnaryClientInterceptor{cc.dopts.unaryInt}, interceptors...)
  8. }
  9. var chainedInt UnaryClientInterceptor
  10. if len(interceptors) == 0 {
  11. chainedInt = nil
  12. } else if len(interceptors) == 1 {
  13. chainedInt = interceptors[0]
  14. } else {
  15. chainedInt = func(ctx context.Context, method string, req, reply interface{}, cc *ClientConn, invoker UnaryInvoker, opts ...CallOption) error {
  16. return interceptors[0](ctx, method, req, reply, cc, getChainUnaryInvoker(interceptors, 0, invoker), opts...)
  17. }
  18. }
  19. cc.dopts.unaryInt = chainedInt
  20. }
  21. func getChainUnaryInvoker(interceptors []UnaryClientInterceptor, curr int, finalInvoker UnaryInvoker) UnaryInvoker {
  22. if curr == len(interceptors)-1 {
  23. return finalInvoker
  24. }
  25. return func(ctx context.Context, method string, req, reply interface{}, cc *ClientConn, opts ...CallOption) error {
  26. return interceptors[curr+1](ctx, method, req, reply, cc, getChainUnaryInvoker(interceptors, curr+1, finalInvoker), opts...)
  27. }
  28. }

总结:

通过层层套娃形式,将拦截器数组变成一个链式拦截器,拦截器的next指向他的下一个拦截器。