2015-07-11 52 views
23

在Go中,有没有一种方法可以匿名满足接口?它似乎并不存在,但这是我最好的尝试。Golang中的匿名接口实现

(在Playground

package main 

import "fmt" 

type Thing interface { 
    Item() float64 
    SetItem(float64) 
} 

func newThing() Thing { 
    item := 0.0 
    return struct { 
     Item (func() float64) 
     SetItem (func(float64)) 
    }{ 
     Item: func() float64 { return item }, 
     SetItem: func(x float64) { item = x }, 
    } 
} 

func main() { 
    thing := newThing() 
    fmt.Println("Hello, playground") 
    fmt.Println(thing) 
} 

回答

27

Go使用method sets声明哪些方法属于一个类型。只有一个声明与接收器类型(方法)的功能的方法:

func (v T) methodName(...) ... { } 

由于嵌套函数被禁止,也没有办法来定义上匿名结构设置的方法。

第二件事不会允许这是方法是只读的。引入了Method values以允许传递方法并在goroutine中使用它们,但不用于操作方法集。

你可以做的反而是提供ProtoThing并指(on play)的匿名结构的底层实现:

type ProtoThing struct { 
    itemMethod func() float64 
    setItemMethod func(float64) 
} 

func (t ProtoThing) Item() float64 { return t.itemMethod() } 
func (t ProtoThing) SetItem(x float64) { t.setItemMethod(x) } 

// ... 

t := struct { ProtoThing }{} 

t.itemMethod = func() float64 { return 2.0 } 
t.setItemMethod = func(x float64) { item = x } 

这工作,因为通过嵌入ProtoThing方法组被继承。因此匿名结构也符合Thing接口。

+1

这实在是真棒,我喜欢它是如何半结构化的。嵌入是非常整洁。 – jocull

+0

起初我读过的部分“不可能的”,但后来回来了,却一直运行它!好一个! –

8

这里是为了满足一个匿名函数的接口非常简洁的方式。

type Thinger interface { 
    DoThing() 
} 

type DoThingWith func() 

// Satisfy Thinger interface. 
// So we can now pass an anonymous function using DoThingWith, 
// which implements Thinger. 
func (thing DoThingWith) DoThing() { 
    // delegate to the anonymous function 
    thing() 
} 

type App struct { 
} 

func (a App) DoThing(f Thinger) { 
    f.DoThing() 
} 


//...Somewhere else in your code: 
app := App{} 

// Here we use an anonymous function which satisfies the interface 
// The trick here is to convert the anonymous function to the DoThingWith type 
// which delegates to the anonymous function 

app.DoThing(DoThingWith(func() { 
    fmt.Println("Hey interface, are you satisfied?") 
})) 

游乐场:https://play.golang.org/p/k8_X9g2NYc

NB,它看起来像HandlerFunc在HTTP包使用此模式:https://golang.org/pkg/net/http/#HandlerFunc

编辑:更改类型DoThing到DoThingWith的清晰度。更新操场

+0

嘿,那真的很干净!干得不错! – jocull

0

无法实例与方法结构,它们需要被声明为功能,但是在Go功能是“一等公民”,所以他们可以像在JavaScript(但键入)字段值。

您可以接受FUNC领域通用的结构来实现接口:

package main 

import "fmt" 

type Thing interface { 
    Item() float64 
    SetItem(float64) 
} 

// Implements Thing interface 
type thingImpl struct { 
    item func() float64 
    setItem func(float64) 
} 
func (i thingImpl) Item() float64  { return i.item() } 
func (i thingImpl) SetItem(v float64) { i.setItem(v) } 

func newThing() Thing { 
    item := 0.0 
    return thingImpl{ 
     item: func() float64 { return item }, 
     setItem: func(x float64) { item = x }, 
    } 
} 

func main() { 
    thing := newThing() 
    fmt.Println("Hello, playground") 
    fmt.Println(thing) 
}