go语言泛型在grpc-client中的使用

2023-08-17  本文已影响0人  鸿雁长飞光不度

通过使用泛型可以减少grpc-client公共代码的重复编写。

// ------------------------------公共的------------------------------------------------------
type clientSvc[T any] struct {
    *grpcpool.Pool
    InitClientCall func(grpc.ClientConnInterface) T
}

func (c *clientSvc[T]) getCli(ctx context.Context) (T, func() error, error) {
    defer timecost.LogFuncTimeCost(ctx)()
    var defaultValue T
    if c.Pool == nil {
        return defaultValue, nil, fmt.Errorf("clientSvcConnPool not initialized yet")
    }

    conn, err := c.Pool.Get(ctx)

    if err != nil {
        return defaultValue, nil, fmt.Errorf("get client svc client err, available=%d capacity=%d err=%w", c.Pool.Available(), c.Pool.Capacity(), err)
    }

    return c.InitClientCall(conn), conn.Close, nil
}

func (c *clientSvc[T]) baseCall(ctx context.Context, reqCall func(T) error) error {
    cli, closeFunc, err := c.getCli(ctx)
    if err != nil {
        return err
    }
    defer func() {
        _ = closeFunc()
    }()

    if reqCall != nil {
        err = reqCall(cli)
        if err != nil {
            return err
        }
    }
    return nil
}

func newBaseClient[T any](addr string, poolCfg *grpcutils.PoolConfig, opts []grpcutils.Option, InitClientCall func(grpc.ClientConnInterface) T) (*clientSvc[T], error) {
    connPool, err := grpcutils.NewGRPCPool(addr, poolCfg, opts...)
    if err != nil {
        return nil, fmt.Errorf("get client svc client err, available=%d capacity=%d err=%w", connPool.Available(), connPool.Capacity(), err)
    }

    return &clientSvc[T]{
        Pool:           connPool,
        InitClientCall: InitClientCall,
    }, nil
}

func (c *clientSvc[T]) Close() {
    if c.Pool != nil && !c.Pool.IsClosed() {
        c.Pool.Close()
    }
}

//------------------------------Client服务的Client------------------------------------------------------

type IClient interface {
    Close()
    GetClientID(ctx context.Context, id uint64) (int64, error)
}

type clientSvcClient struct {
    clientSvc[clientservicepb.InternalServiceClient]
}

func NewClientSvc(addr string, poolCfg *grpcutils.PoolConfig, opts []grpcutils.Option) (IClient, error) {
    c, err := newBaseClient[clientservicepb.InternalServiceClient](addr, poolCfg, opts, func(conn grpc.ClientConnInterface) clientservicepb.InternalServiceClient {
        return clientservicepb.NewInternalServiceClient(conn)
    })
    if err != nil {
        return nil, err
    }
    return &clientSvcClient{
        clientSvc: *c,
    }, nil
}

func (c *clientSvcClient) GetClientID(ctx context.Context, id uint64) (int64, error){
    var resultId int64
    err := c.baseCall(ctx, func(cli clientservicepb.InternalServiceClient) error {
        req := &clientcommonpb.IDRequest{
            Id: clientMemberId,
        }

        resp, err := cli.GetClientIDByClientMemberID(ctx, req)
        if err != nil {
            return err
        }
        resultId = resp.GetData().GetId()
        return nil
    })

    if err != nil {
        return 0,  err
    }
    return resultId, nil
}

上一篇 下一篇

猜你喜欢

热点阅读