存储所有符合相同接口的类型的构造函数集合

时间:2016-12-10 17:20:50

标签: go constructor function-pointers go-interface

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

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

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

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来提供足够的构造函数,但是我很可能想避免这种重复。

感谢您的任何见解!

1 个答案:

答案 0 :(得分:0)

(编辑:我已经接受了我自己的答案,因为缺少任何其他答案,但其中最相关的部分是@seh的评论)

按照@JorgeMarey的评论,并不想牺牲构造函数的类型签名,我想出了这个。但它确实让我觉得非常俗气。我会很高兴听到更清洁的方式。

import org.ehcache.Cache;
import org.ehcache.PersistentCacheManager;
import org.ehcache.config.units.EntryUnit;
import org.ehcache.config.units.MemoryUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.ehcache.config.builders.CacheConfigurationBuilder.*;
import static org.ehcache.config.builders.CacheManagerBuilder.*;
import static org.ehcache.config.builders.ResourcePoolsBuilder.*;

public class Main {

  private static final Logger log = LoggerFactory.getLogger(Main.class);

  public static void main(String[] args) {
    try(PersistentCacheManager persistentCacheManager =
        newCacheManagerBuilder()
            .with(persistence("cache"))
            .withCache("test-cache",
                newCacheConfigurationBuilder(
                    Integer.class, String.class,
                    newResourcePoolsBuilder()
                        .heap(1, EntryUnit.ENTRIES)
                        .offheap(1, MemoryUnit.MB)
                        .disk(20, MemoryUnit.MB, true)
                )
            ).build(true)) {
      Cache cache = persistentCacheManager.getCache("test-cache", Integer.class, String.class);

      log.info("Cache get 1 before putting: " + cache.get(1));
      for (int i = 0; i < 1000; i++) {
        cache.put(i, "Hello");
      }
      log.info("Cache get 1 after putting: " + cache.get(1));
    }
  }
}

(使用/user/login?redirect=/en/about 显式转换的尝试也被编译器认为是不合适的)