Reputation: 1601
I have a plugin that defines following struct:
type foo struct {
counter int64
}
type Plugin struct {}
func (p *Plugin) Do() *foo {
// Do something
return &foo{123}
}
In my main application, I need to cast the plugin to an interface in order to be able to use Do()
. At this moment I do not care about the returned value (pointer to a foo
struct), but it would be nice to have it.
Question, how do I cast and define a valid interface, if I do not have access to the foo
struct? I tried the following options:
type MyFoo struct {
counter int64
}
type PluginInterface interface {
Do() *MyFoo
}
type PluginInterface2 interface {
Do() interface{}
}
func main() {
plugin := Plugin{} // this would be code that loads bar as an interface {} from the plugin
do(&plugin)
}
func do(plugin interface{}) {
_, ok := plugin.(PluginInterface)
fmt.Println("OK with own Struct?", ok) // false
_, ok2 := plugin.(PluginInterface2)
fmt.Println("OK with generic interface?", ok2) // false
}
However, the cast to PluginInterface
and PluginInterface2
fails. Obviously, if I change the method definition of Do()
in the plugin to return a generic interface{}
, then PluginInterface2
cast would succeed.
Example code: https://play.golang.org/p/rB5zZVChSpc
Upvotes: 0
Views: 450
Reputation: 417422
You can't. Change signature of Plugin.Do()
to return a value of type defined outside of the plugin (e.g. defined in a 3rd package used by both your app and the plugin), or to return e.g. interface{}
.
See related questions:
If you can't change the plugin, you may use reflection to call the method. Example calling the Time.Hour()
method:
var x interface{} = time.Date(2019, 1, 1, 14, 0, 0, 0, time.UTC)
v := reflect.ValueOf(x)
hour := v.MethodByName("Hour")
results := hour.Call(nil)
fmt.Println(results[0])
It outputs (try it on the Go Playground):
14
Upvotes: 2