Anonymous interface implementation in Golang
Go uses method sets to declare which methods belong to a type. There is only one way to declare functions with receiver types (methods):
func (v T) methodName(...) ... { }
Since nested functions are forbidden, there is no way to define a method set on anonymous structs.
The second thing that will not allow this is that methods are read-only. Method values were introduced to allow to pass methods around and use them in goroutines but not to manipulate the method set.
What you can do instead is to provide a ProtoThing and refer to underlying implementations of your anonymous struct (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 }
This works because by embedding ProtoThing
the method set is inherited. Thus the anonymous struct also satisfies the Thing
interface.
Here's neat way to satisfy an interface with an anonymous function.
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?")
}))
Playground: https://play.golang.org/p/k8_X9g2NYc
nb, it looks like HandlerFunc in http package uses this pattern: https://golang.org/pkg/net/http/#HandlerFunc
edit: Changed type DoThing to DoThingWith for clarity. Updated playground
You can not instantiate a struct with methods, they need to be declared as functions, but in Go functions are "first class citizens", so they can be field values just like in JavaScript (but typed).
You can make a generic struct that accepts func fields to implement the interface:
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)
}