如果一个接口只有一个方法,我应该使用一个函数类型吗?
以下是两种方法的示例:
type Delegate interface { | type Delegate func(x int) int
Do(x int) int |
} |
|
type App struct { | type App struct {
delegate Delegate | delegate Delegate
} | }
|
func (this *App) foo() { | func (this *App) foo() {
... | ...
y := this.delegate.Do(x) | y := this.delegate(x)
... | ...
} | }
|
func main() { | func main() {
delegate := &DelegateImpl{} | delegate := &DelegateImpl{}
app := &App{delegate} | app := &App{delegate.Process}
... | ...
} | }
试验:
type FakeDelegate { |
t *testing.T |
expectedX int |
result int |
} |
|
func (this *FakeDelegate) Do(x int) int { |
require.Equal(t, this.expectedX, x) |
return this.result |
} |
|
func TestAppFoo(t *testing.T) { | func TestAppFoo(t *testing.T) {
app := &App{} | app := &App{}
app.delegate = &FakeDelegate{t, 1, 2} | app.delegate = func(x int) int {
app.foo() | require.Equal(t, 1, x)
} | return 2
| }
| app.foo()
| }
看起来右边的代码(带有函数类型)的行数较少,特别是在测试时。但是,有没有陷阱?
答案 0 :(得分:8)
这是一个设计问题。接口提供的功能不是动态调度。因此,如果您以后希望(可能是您自己的)客户端代码将所述函数应用于对象,并设想该对象可能是程序中某个给定点的几种不同类型之一,那么请选择一个接口。
专业人士:你可以灵活变通。
缺点:
Go被设计为一种简单实用的语言。我认为,作为有意愿的用户,我们应该发扬其理念。因此,我要说:如果你不需要某些东西,就不要使用它。 :)
尽管函数指针确实是开发人员管理的动态调度的一种形式,但在我看来,上述推理仍然适用:寻找可满足可预见需求的最简单的解决方案。否则Go将成为Java。如果您确定代理人永远不需要提供任何其他入口点(例如提供元信息),我会说坚持使用函数指针。
答案 1 :(得分:3)
我认为使用以下简单规则是合理的:
io.Reader
接口,使用单个方法Read
。http.HandlerFunc
,bufio.SplitFunc
我也发现好名字有助于设计决策。