【问题标题】:Implementing interface method with variable arguments使用可变参数实现接口方法
【发布时间】:2015-10-13 23:52:35
【问题描述】:

我从简单的界面开始:

type Module interface {
    Init(deps ...interface{}) error
}

我想,实现会非常简单,因为这个方法应该匹配任意数量的提供的参数。这就是我最终得到这段代码的结果,我想,TestModule 实现了Module 接口。

type TestModule struct {
}

func (m *TestModule) Init(str string) error {
    return nil
}

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

不能在 testFunc 的参数中使用模块(类型 *TestModule)作为类型模块:

func testFunc(module Module) {

}

编辑:是否有实现这种行为的最佳实践?

【问题讨论】:

    标签: go interface


    【解决方案1】:

    这没有实现接口;

    func (m *TestModule) Init(str string) error {
        return nil
    }
    

    你的困惑出现在“因为这个方法应该匹配任意数量的提供的参数”这是一个语言特性,它允许 调用者 使用可变数量的参数调用方法(见这里@ 987654321@)。要实现它,您需要实现相同的签名含义... interface{}

    所以要明确一点,“提供的任意数量的参数”仅用于调用该方法,这并不意味着您可以使用任何类型的任何一组参数来实现该方法,并且它将具有相同的定义。定义指出,调用者传入的实现interface{} 的项目数量不定。

    “是否有实现这种行为的最佳实践?”

    我不知道。我认为通常的做法是放宽传递给interface{}... interface{} 的类型,然后检查方法内的集合。例如,如果Module 接口的定义为Init(deps interface{}) error,那么您可以像这样在测试模块中实现它;

    func (m *TestModule) Init(deps interface{}) error {
          str := deps.(string)
          return nil
    }
    

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

    【讨论】:

    • @Gelidus 对此我情不自禁,但我给了你两分钱。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多