使用可变参数实现接口方法

pet*_*ina 1 interface go

我从简单的界面开始:

type Module interface {
    Init(deps ...interface{}) error
}
Run Code Online (Sandbox Code Playgroud)

我想,实现将非常简单,因为这个方法应该匹配任意数量的提供的参数.这就是我最终得到的代码,思考,TestModule实现Module接口.

type TestModule struct {
}

func (m *TestModule) Init(str string) error {
    return nil
}
Run Code Online (Sandbox Code Playgroud)

但是,当我想将TestModule传递给任何需要Module的函数时,我收到此错误:

不能将模块(类型*TestModule)用作testFunc参数中的类型Module:

func testFunc(module Module) {

}
Run Code Online (Sandbox Code Playgroud)

编辑:有没有最佳实践来实现这种行为?

eva*_*nal 6

这没有实现接口;

func (m *TestModule) Init(str string) error {
    return nil
}
Run Code Online (Sandbox Code Playgroud)

你的混淆出现在"因为这个方法应该匹配任何数量的提供的参数"这是一个语言特性,它允许调用者使用可变数量的参数调用方法(参见这里"..."的意思是什么时候旁边的go函数声明中的参数?).要实现它,您需要实现相同的签名含义... interface{}.

所以要明确的是,"任意数量的提供参数"仅用于调用方法,这并不意味着您可以使用任何类型的任何参数集来实现该方法,并且它将具有相同的定义.该定义表明interface{}调用者传入的项目将有可变数量.

"有没有最好的做法来实施这种行为?"

从来没听说过.我认为通常的做法是放宽传入的类型interface{}或者... interface{}然后检查方法内的集合.例如,如果Module接口具有它的定义,Init(deps interface{}) error那么您可以在测试模块中实现它,就像这样;

func (m *TestModule) Init(deps interface{}) error {
      str := deps.(string)
      return nil
}
Run Code Online (Sandbox Code Playgroud)

如果你想要可变长度的args,你只需要for range在方法中添加一个构造来取消装箱值或进行一些边界检查.我不能说这是否适合您的应用程序,因为我认为这取决于您使用单一方法sig获得多少价值.它增加了额外的锅炉板代码,并且有一些轻微的性能损失.