0

我正在制作一个需要一组规则来运行工作的应用程序。该应用程序提供了用几种不同语言中的一种来表达规则的可能性。因此,我为实时规则引擎定义了一个接口,它提供了应用程序查询当前规则集所需的方法。在这个界面后面,根据源语言,会有一种不同类型的引擎。

现在我想根据规则文件的扩展名实例化一个规则引擎。但是我遇到了一些我很难克服的错误。

让我首先提供这个简化的骨架:

package main

//
//
// The interface

type RulesEngine interface {
    SomeRuleEvaluator(string) bool
}

//
//
// An implementation, with its constructor

type ASimpleRulesEngine struct {
    // I've also tried with :
    // RulesEngine
}

func NewASimpleRulesEngine(context string) *ASimpleRulesEngine {
    re := ASimpleRulesEngine{}
    return &re
}

func (re *ASimpleRulesEngine) SomeRuleEvaluator(dummy string) bool {
    return true
}

//
//
// A client, that'll want to be able to choose a constructor

var rulesEngineConstructorsPerExtension map[string](func(string) RulesEngine)

func init() {
    rulesEngineConstructorsPerExtension = make(map[string](func(string)RulesEngine))
    rulesEngineConstructorsPerExtension[".ini"] = NewASimpleRulesEngine
}

func main() {
}

当我尝试构建它时,我得到35: cannot use NewASimpleRulesEngine (type func(string) *ASimpleRulesEngine) as type func(string) RulesEngine in assignment

我也试过:

  • 在没有指针的情况下进行分配,尽管我在尝试时感到很愚蠢
  • 在函数中有一个中间步骤init,我将在其中创建一个new(func (string) RulesEngine)然后分配给它,有和没有指针。
  • 像在 C 中一样存储函数指针,但编译器说它无法获取我的函数的地址。

我对 Go 不太熟悉,这有点令人惊讶。什么是正确的类型签名使用?这可能吗?如果这是不可避免的,我显然会在一侧有一个简单的扩展数组(以检查文件是否可能是规则文件),而switch在另一侧有一个大的扩展来提供足够的构造函数,但尽可能我会想避免这样的重复。

感谢您的任何见解!

4

1 回答 1

0

(已编辑:由于没有其他答案,我已经接受了自己的答案,但其最相关的部分是@seh 下面的评论)


在@JorgeMarey 的评论之后,不想牺牲构造函数的类型签名,我想出了这个。但这对我来说确实很俗气。我很高兴听到更清洁的方法。

func init() {
    rulesEngineConstructorsPerExtension = make(map[string](func(string)RulesEngine))

    cast_NewASimpleRulesEngine := func(content string) RulesEngine {
        return NewASimpleRulesEngine(content)
    }

    rulesEngineConstructorsPerExtension[".ini"] = cast_NewASimpleRulesEngine
}

(func(string)RulesEngine)( NewASimpleRulesEngine)(编译器也认为显式转换的尝试不适合)

于 2016-12-10T18:41:07.307 回答