Something like lambda expressions in Go (merge similar methods)

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

Something like lambda expressions in Go (merge similar methods)

问题

我可以帮你翻译这段代码。你想要在Go语言中实现一个通用方法,这个方法会调用一些公共方法,然后再调用传入的方法,最后根据错误情况调用另一个公共方法并返回结果。这个通用方法会被多个其他方法调用,这些方法的参数和返回类型都不相同。

以下是翻译好的代码:

func (s *service) CommonMethod(method func() (interface{}, error)) (interface{}, error) {
    CommonMethod1()
    CommonMethod2()

    result, err := method()

    if err != nil {
        CommonMethod3()
    }
    return result, err
}

func (s *service) GetUser(i int, s string) (*SomeObject, error) {
    return s.CommonMethod(func() (interface{}, error) {
        return s.internalLayer.GetUser(i, s)
    }).(*SomeObject), err
}

func (s *service) CheckUser(i int) (bool, error) {
    return s.CommonMethod(func() (interface{}, error) {
        return s.internalLayer.CheckUser(i)
    }).(bool), err
}

通过创建一个名为CommonMethod的通用方法,你可以将重复的代码提取出来,并在其他方法中调用它。这个通用方法接受一个函数作为参数,该函数代表了不同方法的具体实现。在GetUserCheckUser方法中,你可以通过调用CommonMethod来实现相同的逻辑,同时传入不同的方法作为参数。

这样,你就可以通过以下方式调用这些方法:

user, err := s.GetUser(i, s)
exists, err := s.CheckUser(i)

这些方法的参数和返回类型可以是不同的,因为它们都通过CommonMethod来处理。

英文:

I have a struct in Go which has more than ten methods. And all of them are almost the same. In fact, the difference is only in one line.

Let's see the simplified example. Here is the first method:

func (s *service) GetUser(i int, s string) (*SomeObject, error) {
    CommonMethod1()
    CommonMethod2()
    
    user, err := s.internalLayer.GetUser(i, s)
    
    if err != nil {
	    CommonMethod3()
    }
    return user, err
}

And the second one:

func (s *service) CheckUser(i int) (bool, error) {
    CommonMethod1()
    CommonMethod2()
    
    exists, err := s.internalLayer.CheckUser(i)
    
    if err != nil {
	    CommonMethod3()
    }
    return exists, err
}

And there are almost 10 others with a lot of copy and paste. I'd like to ameliorate this code and the idea is to create some common method that I'll call everywhere.

It should

  • call CommonMethod1()
  • call CommonMethod2()
  • call some method that I pass to it in the parameter
  • call CommonMethod3() in case of error
  • return parameters

Can you tell me if it's possible to implement in Go such common method?

user, err := s.GetUser(i, s)
exists, err := s.CheckUser(i)

Has different parameters count and different return types.

答案1

得分: 2

如果CommonMethod1()CommonMethod2()的调用不必在内部层的调用之前进行,基本上它们可以合并到一个检查函数中,而且你甚至不需要闭包或函数值(也不需要从check()返回传递的错误):

func (s *service) GetUser(i int, s string) (*SomeObject, error) {
    user, err := s.internalLayer.GetUser(i, s)
    check(err)
    return user, err
}

func (s *service) CheckUser(i int) (bool, error) {
    exists, err := s.internalLayer.CheckUser(i)
    check(err)
    return exists, err
}

func check(err error) {
    CommonMethod1()
    CommonMethod2()
    if err != nil {
        CommonMethod3()
    }
}

如果CommonMethod1()CommonMethod2()的调用必须在内部层的调用之前进行,那么你可以使用闭包,但是使用命名返回参数可以简化代码,并且再次强调,不需要从公共函数返回错误:

func (s *service) GetUser(i int, s string) (user *SomeObject, err error) {
    do(func() error {
        user, err = s.internalLayer.GetUser(i, s)
        return err
    })
    return
}

func (s *service) CheckUser(i int) (exists bool, err error) {
    do(func() error {
        exists, err = s.internalLayer.CheckUser(i)
        return err
    })
    return
}

func do(f func() error) {
    CommonMethod1()
    CommonMethod2()

    if err := f(); err != nil {
        CommonMethod3()
    }
}
英文:

If CommonMethod1() and CommonMethod2() calls do not have to precede the calls to the internal layer, basically they can be incorporated into a check function, and you don't even need closures or function values (there's also no need to return the passed error from check()):

func (s *service) GetUser(i int, s string) (*SomeObject, error) {
    user, err := s.internalLayer.GetUser(i, s)
	check(err)
	return user, err
}

func (s *service) CheckUser(i int) (bool, error) {
    exists, err := s.internalLayer.CheckUser(i)
	check(err)
	return exists, err
}

func check(err error) {
	CommonMethod1()
	CommonMethod2()
	if err != nil {
		CommonMethod3()
	}
}

If CommonMethod1() and CommonMethod2() calls must precede the calls to the internal layer, then you may use closures, but using named result parameters simplifies the code, and again, it's unnecessary to return the error from the common function:

func (s *service) GetUser(i int, s string) (user *SomeObject, err error) {
	do(func() error {
		user, err = s.internalLayer.GetUser(i, s)
		return err
	})
	return
}

func (s *service) CheckUser(i int) (exists bool, err error) {
	do(func() error {
		exists, err = s.internalLayer.CheckUser(i)
		return err
	})
	return
}

func do(f func() error) {
	CommonMethod1()
	CommonMethod2()

	if err := f(); err != nil {
		CommonMethod3()
	}
}

答案2

得分: 1

你可以使用闭包来实现DRY(Don't Repeat Yourself):

func GetUser2(i int, s string) (*User, error) {
    var u *User
    err := do(func() error {
        var err error
        u, err = getUser(i, s)
        return err
    })
    return u, err
}

func CheckUser2(i int) (bool, error) {
    var b bool
    err := do(func() error {
        var err error
        b, err = checkUser(i)
        return err
    })
    return b, err
}

func do(f func() error) error {
    CommonMethod1()
    CommonMethod2()

    err := f()
    if err != nil {
        CommonMethod3()
    }
    return err
}

以上代码使用闭包来实现DRY(Don't Repeat Yourself)。在GetUser2CheckUser2函数中,通过调用do函数来执行具体的逻辑,并在需要的地方进行错误处理。do函数中的f参数是一个函数类型,通过闭包的方式将具体的逻辑传递进去。在do函数中,首先执行一些公共方法CommonMethod1CommonMethod2,然后执行传入的函数f,如果出现错误,则执行CommonMethod3。最后,返回可能发生的错误。

英文:

You can DRY it using closures:

func GetUser2(i int, s string) (*User, error) {
	var u *User
	err := do(func() error {
		var err error
		u, err = getUser(i, s)
		return err
	})
	return u, err
}

func CheckUser2(i int) (bool, error) {
	var b bool
	err := do(func() error {
		var err error
		b, err = checkUser(i)
		return err
	})
	return b, err
}

func do(f func() error) error {
	CommonMethod1()
	CommonMethod2()

	err := f()
	if err != nil {
		CommonMethod3()
	}
	return err
}

huangapple
  • 本文由 发表于 2017年7月5日 18:14:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/44923323.html
匿名

发表评论

匿名网友

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

确定