Golang,带有指针和接口的用例
I am writing a library I'll need to use in others parts of my programs, for this I had to use a lot interfaces and I ended up in a case I don't know how to solve.
Here is my code :
main.go
package main
import (
"test/bar"
)
// Foo is defined in another package
type Foo struct {
WhatWeWant string
}
func (f *Foo) getResult() interface{} {
return f.WhatWeWant
}
func newFoo() interface{} {
return &Foo{
WhatWeWant: "test",
}
}
func main() {
bar := bar.Bar{
NewFooer: newFoo,
}
bar.Execute()
}
bar/bar.go
package bar
import (
"fmt"
"reflect"
)
type myInterface interface {
getResult() interface{}
}
type Bar struct {
NewFooer func() interface{}
}
func (b *Bar) Execute() {
foo := b.NewFooer()
// executeLib only accept pointer
executeLibWrapper(foo)
whatWeWant := foo.(myInterface).getResult()
fmt.Println(whatWeWant)
fmt.Println("Win!")
}
// This function is executed in an external library I have no control on
func executeLibWrapper(src interface{}) {
executeLib(reflect.TypeOf(src))
}
func executeLib(src reflect.Type) {
if src.Kind() == reflect.Ptr {
executeLib(src.Elem())
return
}
switch src.Kind() {
case reflect.Struct:
fmt.Println("Struct OK!")
default:
panic(fmt.Sprintf("Can't detect struct, we detect %s", src.Kind()))
}
}
I get the error
panic: interface conversion: *main.Foo is not bar.myInterface: missing method getResult
My goal is to be able to call getResult() after executing the library. Here is a playground : https://play.golang.org/p/7G2wc6uGngH. This playground works, so there is a strong possibilities that the problem come from the fact it is in different packages.
Note that I need to pass a pointer to executeLib, I can't get the pointer in execute() because otherwise I'll lose the foo type and can't execute the library : https://play.golang.org/p/A8ETfuMQyQB. This is why I have to return the pointer in newFoo()
Thank you for your help !
If you want to share an interface and their funcs across packages you have export the interface and its funcs:
type MyInterface interface {
GetResult() interface{}
}
When you change the implementation of Foo
func (f *Foo) GetResult() interface{} {
return f.WhatWeWant
}
and the call
whatWeWant := foo.(MyInterface).GetResult()
it compiles and executes without panic.
Got the result here. Hope this can help.
Seems the trick is using these. Adding these snippet introduces the smallest impact on code.
Just make NewFooer
a member function of Bar
. When NewFooer
is invoked newFoo
is called.
func (m *Bar) NewFooer() interface{} {
return newFoo()
}
Eventually this snippet is invoked as well
func newFoo() interface{} {
return &Foo{
WhatWeWant: "test",
}
}