Go插件与应用间能否共享自定义类型?能否断言为结构体?
可以将Go插件导出的符号断言为结构体吗?
当然可以!不过要让这个操作成功,有个核心要求:你的主程序必须定义和插件里完全一致的结构体类型——包括包路径、字段名、字段类型,甚至字段顺序都得丝毫不差,因为Go的类型系统是通过类型的完整定义(包括所属包)来判断类型相等性的。
下面是完整的可运行示例,帮你理解具体怎么实现:
插件代码(plugin.go)
这就是你提供的插件代码,导出了一个Person结构体实例:
package main type Person struct { Name string } var ( P = Person{ Name: "Emma", } )
主程序代码(app.go)
主程序里必须先定义和插件完全匹配的Person结构体,然后通过插件查找符号并完成类型断言:
package main import ( "fmt" "plugin" "os" ) // 关键:和插件中的Person结构体定义完全一致 type Person struct { Name string } func main() { // 加载插件 plug, err := plugin.Open("./plugin.so") if err != nil { fmt.Println("加载插件失败:", err) os.Exit(1) } // 查找导出的符号P symP, err := plug.Lookup("P") if err != nil { fmt.Println("查找符号失败:", err) os.Exit(1) } // 类型断言为*Person // 注意:插件导出的变量,Lookup返回的是指向该变量的指针,所以要断言为指针类型 p, ok := symP.(*Person) if !ok { fmt.Println("类型断言失败:符号不是预期的*Person类型") os.Exit(1) } // 正常使用结构体 fmt.Printf("从插件获取到的Person实例:%+v\n", p) fmt.Println("姓名:", p.Name) // 额外:还可以修改插件里的变量值(如果业务需要) p.Name = "Liam" fmt.Printf("修改后插件中的Person实例:%+v\n", p) }
编译与运行步骤
- 编译插件:
go build -buildmode=plugin -o plugin.so plugin.go
- 运行主程序:
go run app.go
关键注意事项
- 类型完全匹配:哪怕结构体的字段顺序变了、字段名大小写错了、或者包路径不一致,类型断言都会失败。比如如果插件里的结构体是
pkg.Person,主程序里也必须在pkg包下定义完全一样的Person。 - 断言为指针类型:插件导出的变量,
Lookup返回的是指向该变量的指针,所以要断言为*Person而非Person。如果插件里导出的是结构体指针变量(比如var P *Person = &Person{...}),那主程序就要断言为**Person。
内容的提问来源于stack exchange,提问作者felipeek
相关产品推荐
相关产品推荐

