【问题标题】:Something like lambda expressions in Go (merge similar methods)Go 中的 lambda 表达式之类的东西(合并类似的方法)
【发布时间】:2017-07-05 10:14:54
【问题描述】:

我在 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)

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

【问题讨论】:

  • 在你的例子中,每个方法都无条件地调用自己,这不是无休止的“递归”吗?
  • 好话。我简化了很多。实际上它调用了一些内部层。 s.internalLayer.CheckUser(i) 已更正。

标签: go lambda closures dry


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您可以使用闭包将其干燥:

    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
    }
    

    【讨论】:

      猜你喜欢
      • 2012-07-30
      • 2018-07-09
      • 2015-11-03
      • 2011-05-08
      • 1970-01-01
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 2019-12-19
      相关资源
      最近更新 更多