how to avoid go lint duplication for same pattern with different function?

Issue

I have difficulties refactoring code in go, since the lint detects duplication of pattern but the function is different.

the code goes like this, it is implemented for grpc with protobuf definition

func (svc *UserService) CreateUser(ctx context.Context, req *pb.CreateUserRequest) (*pb.CreateUserResponse, error) {
    err := svc.validateCreateUser(req)
    if err != nil {
        return nil, err
    }

    user, err := svc.repo.CreateUser(ctx, req)

    if err != nil {
        return nil, err
    }

    return user, nil
}

func (svc *UserService) UpdateUser(ctx context.Context, req *pb.UpdateUserRequest) (*pb.UpdateUserResponse, error) {
    err := svc.validateUpdateUser(req)
    if err != nil {
        return nil, err
    }

    user, err := svc.repo.UpdateUser(ctx, req)

    if err != nil {
        return nil, err
    }

    return user, nil
}

thanks in advance.

I have no clue how to avoid duplication since the function also have different param type.

Solution

Not all lint issues must be fixed

If you think it will sacrifice readability, add a // nolint

However… you can refactor them code using generics


func [T, V any] someNameToBeDefined(
    ctx context.Context,
    target T,
    validator func(T) error,
    executor func(context.Context, T) (V, error),
    ) (V, error){
    if err := validator(target); err!= nil { … }
    return executor(ctx, target)
}

func (svc *UserService) CreateUser(
   ctx context.Context, 
   req *pb.CreateUserRequest,
) (*pb.CreateUserResponse, error) {
  return someNameToBeDefined(ctx,
     req,
     svc.validateCreateUser,
     svc.repo.CreateUser,
    )
}

If you think this is readable, go ahead.

But perhaps this may not the right way.

For instance, your repo can validate the request before create/update.

This is a more readable approach than use generics and function pointers IMHO

Answered By – Tiago Peczenyj

Answer Checked By – David Marino (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.