Roman Semko
Roman Semko

Reputation: 1601

Cast Method with return value to a method with interface{}

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

Answers (1)

icza
icza

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

Related Questions