您想要的东西是可能的,但是在后台有一些东西使它无法工作。
这即是要查找一个 变量
命名
Greeter从插件。
Plugin.Lookup()将返回一个指向该变量的指针!如果不能,则只能检查其值,但不能更改它。
您可以通过简单地打印存储在中的值的类型来验证这一点
sym:
fmt.Printf("%Tn", sym)在您的第一种情况下
func getPlugin() testpl,输出将是:
*main.testpl
在第二种情况下
func getPlugin() iface.IPlugin,输出将是:
*iface.IPlugin
(是的,它是一个接口的指针!)
在第三种情况下
func getPlugin() interface{},输出将是:*interface {}因此,您的第一个示例之所以有效,
sym是因为其中存储的值的类型
*main.testpl也是,它也实现了
iface.IPlugin(因为
main.testpl实现了,指针类型也实现了)。
回到您的第二个示例:
func getPlugin() iface.IPlugin
存储在中的值
sym是类型
*iface.IPlugin。指向接口的指针类型的值永远不会满足任何接口(空接口除外),因此尝试从type
iface.IPlugin值进行类型断言
*iface.IPlugin将永远不会成功。您必须输入assert
*iface.IPlugintype,然后可以对其进行引用以获取type的值
iface.IPlugin。它可能看起来像这样:
pgPtr, ok := sym.(*iface.IPlugin)if !ok { panic(errors.New("error binding plugin to interface"))}pg := *pgPtr现在一切都按预期工作!
为避免此类麻烦和混乱,您可以实现插件以公开返回以下内容的 函数
Greeter:
func Greeter() iface.IPlugin { return testpl{} }然后
Greeter当然要摆脱全局变量。如果这样做,您可以查找以下
Greeter类型的符号:
func() iface.IPlugin
区别在于查找函数不需要
plugin包返回指向该值的指针,而对于变量则需要。简单的函数类型,没有指向接口的功夫指针。用它来获得迎宾员将是:
Greeter, err := p.Lookup("Greeter")if err != nil { panic(err)}greeterFunc, ok := GetFilter.(func() iface.IPlugin)if !ok { panic(errors.New("not of expected type"))}greeter := greeterFunc()// And using it:fmt.Printf("You're now connected to: %s n", greeter.WhatsYourName())greeter.SayHello("user")greeter.SayGoodby("user")


