2015-10-13 43 views
1

我开始用简单的界面:实现接口方法与变量参数

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

我以为,实施将是非常简单的,因为这种方法应该匹配任意数量的提供的参数。这就是我用这个代码结束的想法,TestModule实现了Module接口。

type TestModule struct { 
} 

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

但是,当我想将TestModule传递给希望模块的所有功能,我得到这个错误:

cannot use module(type *TestModule) as type Module in argument to testFunc:

func testFunc(module Module) { 

} 

编辑:有没有实施这种行为的任何最佳实践?

回答

6

这没有实现接口;

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

如果你产生了困惑是“因为这种方法应该匹配任意数量的提供论据”这是一个语言功能,它可以让呼叫者调用方法与参数个数可变(见这里What does "..." mean when next to a parameter in a go function declaration?) 。要实现它,你需要实现相同的签名... interface{}

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

“是否有任何实施这种行为的最佳做法?”

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

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

如果你想args来变长,你只需要添加一个for range构建到方法拆箱的价值或做一些边界检查。我不能说这在你的应用程序中是否会是一种好的做法,因为我认为这取决于你从一个单一的方法签名中得到多少价值。它增加了额外的锅炉板代码,并有一些小的性能损失。

+0

我编辑了帖子。感谢您的快速回复。 – Gelidus

+0

@Gelidus我不能帮上忙,但我给了你我的两分钱。 – evanmcdonnal