如何避免在不同函数中使用相同模式时出现重复的 Go Lint 代码?

huangapple go评论83阅读模式
英文:

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

问题

我在重构Go代码时遇到了困难,因为代码检查工具检测到了模式的重复,但函数是不同的。

代码如下,它是使用protobuf定义的grpc实现的:

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
}

提前感谢。

我不知道如何避免重复,因为这两个函数的参数类型也不同。

英文:

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.

答案1

得分: 1

并非所有的lint问题都必须修复

如果你认为修复会牺牲可读性,可以添加 // nolint 注释

然而...你可以使用泛型重构代码


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,
    )
}

如果你认为这样可读性更好,可以继续。

但也许这不是正确的方式。

例如,你的repo可以在创建/更新之前验证请求。

在我看来,这种方法比使用泛型和函数指针更可读。

英文:

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

huangapple
  • 本文由 发表于 2022年3月25日 10:03:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/71611375.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定