joc*_*ull 41 anonymous-types go
在Go中,有没有办法匿名满足界面?它似乎没有,但这是我最好的尝试.
(在游乐场)
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)
}
Run Code Online (Sandbox Code Playgroud)
nem*_*emo 47
Go使用方法集来声明哪些方法属于某个类型.使用接收器类型(方法)声明函数只有一种方法:
func (v T) methodName(...) ... { }
Run Code Online (Sandbox Code Playgroud)
由于禁止嵌套函数,因此无法在匿名结构上定义方法集.
不允许这样做的第二件事是方法是只读的.引入方法值以允许传递方法并在goroutine中使用它们但不操纵方法集.
你可以做的是提供一个ProtoThing并引用你的匿名结构的底层实现(在游戏中):
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 }
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为嵌入ProtoThing方法集是继承的.因此匿名结构也满足Thing接口.
All*_*ton 11
这是满足匿名函数接口的简洁方法.
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?")
}))
Run Code Online (Sandbox Code Playgroud)
游乐场:https://play.golang.org/p/k8_X9g2NYc
nb,看起来http包中的HandlerFunc使用这种模式:https://golang.org/pkg/net/http/#HandlerFunc
编辑:为了清楚起见,将类型DoThing更改为DoThingWith.更新了游乐场
你不能用方法实例化一个结构体,它们需要被声明为函数,但在 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)
}
Run Code Online (Sandbox Code Playgroud)