像Go中的lambda表达式(合并类似的方法)

时间:2017-07-05 10:14:55

标签: go lambda closures dry

我在Go中有一个结构,它有十多种方法。而且他们几乎都是一样的。事实上,差异只在一行。

让我们看一下简化的例子。这是第一种方法:

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
}

第二个:

func (s *service) CheckUser(i int) (bool, error) {
    CommonMethod1()
    CommonMethod2()

    exists, err := s.internalLayer.CheckUser(i)

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

还有近10个人有很多复制和粘贴。我想改进这个代码,我的想法是创建一些我将在任何地方调用的常用方法。

应该

  • 致电CommonMethod1()
  • 致电CommonMethod2()
  • 调用我在参数
  • 中传递给它的一些方法
  • 如果出现错误,请致电CommonMethod3()
  • 返回参数

你能告诉我是否可以用Go这样的常用方法实现?

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

具有不同的参数计数和不同的返回类型。

2 个答案:

答案 0 :(得分:3)

如果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()调用必须先于对内部图层的调用,那么您可以使用闭包,但使用named result parameters可以简化代码,并且再次使用它不需要从公共函数返回错误:

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

答案 1 :(得分:1)

你可以使用闭包来干它:

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
}