微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在Go中概括函数包装?

如何解决如何在Go中概括函数包装?

我有以下界面:

type Selector interface {
    SelectOne(ctx context.Context,one A) (Result,error)
    SelectTwo(ctx context.Context,one A,two B) ([]Result,error)
    SelectThree(ctx context.Context,two B,three C) ([]Result,error)
}

和以下实现:

type Database struct{}
func (d Database) SelectOne(...) (...) {...}
func (d Database) SelectTwo(...) (...) {...}
func (d Database) SelectThree(...) (...) {...}

然后,最重要的是,我想添加一个使用非常漂亮的github.com/hashicorp/golang-lru库的缓存层:

type SelectorCache struct {
    db        Database
    cacheOne *lru.Cache
    cacheTwo *lru.Cache
}

func (c SelectorCache) SelectOne(ctx context.Context,error) {
    cached,ok := c.cacheOne.Get(makeKey(one))
    if ok {
        casted,ok := cached.(Result)
        if ok {
            return casted,nil
        }
    }
    fetched,err := c.db.SelectOne(ctx,one)
    if err != nil {
        return Result{},err
    }
    c.cache.Add(key,fetched)
    return fetched,nil
}

func (c SelectorCache) SelectTwo(ctx context.Context,error) {
    ...
        casted,ok := cached.([]Result)
    ...
    fetched,err := c.db.SelectTwo(ctx,one,two)
    ...
}

func () SelectThree(ctx context.Context,err := c.db.SelectThree(ctx,two,three)
    ...
}

如您所见,每种情况下的缓存层基本相同,唯一的区别在于底层函数。如果是Python,我可以轻松创建将* a,** kw传递给包装函数的包装函数。我该如何重写,以使样板消失?

解决方法

您可以编写一个可变参数函数(请参见Function types),该函数以任意数量的int作为参数(零个或多个),并一次性处理它们。例如

func (d Database) Select(ctx context.Context,numbers ...int)

您可以在numbers的循环中遍历range并执行所需的操作。您的函数调用可以保持与以前相同。

fetched,err := c.db.Select(ctx,one)
fetched,one,two)
fetched,two,three)
,

您在评论中提到参数类型有所不同。

通常,您可以这样做:

  • 在编译时,或
  • 在运行时。

运行时版本更易于编码和使用,并且非常灵活,但是当然会花费一些运行时成本。也许您正在尝试避免这种情况(很好,但是请记住关于在优化之前进行测量的古老说法)。

您在示例中编写的是编译时版本。

我该如何重写,以使样板消失?

对于Go 1,只有一种方法可以做到:编写程序来编写程序。 {这就是go generate的全部内容。也有一个Go blog post

在Go 2中,几乎可以肯定会有generics,您可以实际使用它们。它们将成为您想要做的方式。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。