我知道可以查找导出的go-plugin符号并将其键入到界面中。但是,我想知道是否有办法将它们键入到结构中。有没有办法做到这一点?
例如:
插件.go
package main
type Person struct {
Name string
}
var (
P = Person{
Name: "Emma",
}
)
app.go
package main
import (
"fmt"
"plugin"
"os"
)
func main() {
plug, err := plugin.Open("./plugin.so")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
sym, err := plug.Lookup("P")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
var p Person
p, ok := sym.(Person)
if !ok {
fmt.Println("Wrong symbol type")
os.Exit(1)
}
fmt.Println(p.Name)
}
符号 P,即人,在插入时找到。调用查找。但是,我无法将 P 键入到个人中,我收到执行时间错误。在此示例中,"错误的符号类型"。
有没有办法实现这一点,或者在插件和应用程序之间共享数据的唯一方法是使用接口?
谢谢。
main
包中定义的标识符不能从其他包中引用,因此从插件导出的标识符不能与您在主应用程序中的类型相同。即使您在插件的文件和主应用程序中复制Person
类型,类型断言也会失败,因为它们不是同一类型!
但是可以在单独的包中定义类型,并在插件和主应用程序中使用相同的包。然后,您可以从从插件中查找的符号中键入断言此类型。
请参阅此示例:
在其自己的包中定义的单独类型:
package filter
type Filter struct {
Name string
Age int
}
插件代码:
package main
import (
"play/filter"
)
var MyFilter = filter.Filter{
Name: "Bob",
Age: 21,
}
func CreateFilter() filter.Filter {
return filter.Filter{
Name: "Bob",
Age: 21,
}
}
主应用程序:
package main
import (
"fmt"
"log"
"os"
"play/filter"
"plugin"
)
func main() {
p, err := plugin.Open("plugin.so")
if err != nil {
log.Fatal(err)
}
mf, err := p.Lookup("MyFilter")
if err != nil {
log.Fatal(err)
}
f, ok := mf.(*filter.Filter)
if !ok {
log.Fatal("Wrong symbol type")
}
fmt.Printf("%+vn", f)
}
运行主应用,输出为:
&{Name:Bob Age:21}
您可能会注意到,插件MyFilter
中导出的标识符是非指针类型的变量,但我们从导出的符号中类型断言了指针类型。这是因为如果你查找一个变量,你会得到一个指向它的指针,否则你不能修改变量的值,你只能修改副本。这在这个答案中有详细说明:插件符号作为函数返回
如果我们查找插件导出的另一个符号,情况并非如此:返回非指针类型值的CreateFilter()
函数filter.Filter
:
cf, err := p.Lookup("CreateFilter")
if err != nil {
log.Fatal(err)
}
createFilter, ok := cf.(func() filter.Filter)
if !ok {
log.Fatal("Wrong function type")
}
f2 := createFilter()
fmt.Printf("%+vn", f2)
运行此代码,输出将为:
{Name:Bob Age:21}
查看相关问题: go 1.8 插件使用自定义界面
另请注意,如果您更改插件和主应用程序常用的filter
包,您还必须重建插件。尝试在不重新构建插件的情况下运行应用程序将导致在plugin.Open()
调用期间出错。有关详细信息,请参阅 Go 插件依赖项如何工作?