英文:
golang: how to unload an already loaded "go plugin" 1.8
问题
从Go 1.8开始,Go语言支持创建和加载插件。
但是,不支持卸载插件。
插件是在运行时加载的模块,是否可能卸载一个模块?
如果无法卸载模块,那么在应用程序级别上,如何使插件无法使用但仍保留在内存中是最好的解决方案?
英文:
go1.8 onwards, go supports to create and load a plugin.
but unload plugin is not supported.
a plugin is a module loaded at runtime, is it possible to unload a module?
if not possible to unload a module, what is the best that can be done at application level to unload a plugin/make it unusable but still in memory?
答案1
得分: 1
Go语言不支持卸载插件,但你可以像你建议的那样禁用它。通常,插件会定义一个包含有关插件信息的结构体。你可以从一个名字已知的工厂函数中返回这个结构体(例如,awesome.so
包含 AwesomePlugin
)。在结构体中,你可以包含一个禁用插件访问的方法。你可以这样做:
type MyPlugin struct {
Name string
Enable func() error
Disable func() error
}
然后,在插件本身中,你可以这样做:
var (
awesomeEnabled bool
)
func AwesomePlugin() *myplugin.MyPlugin {
return &myplugin.MyPlugin{
Name: "AwesomePlugin",
Enable: func() error {
println("Enabling AwesomePlugin")
awesomeEnabled = true
return nil // or do something more complex that could error
},
Disable: func() error {
println("Disabling AwesomePlugin")
awesomeEnabled = false
return nil // or do something more complex that could error
},
}
}
然后,加载、启用和禁用插件的代码将如下所示:
awesomePlugin, err := plugin.Open("awesome.so")
if err != nil {
panic("Can't load plugin: " + err.Error())
}
sym, err := awesomePlugin.Lookup("AwesomePlugin")
if err != nil {
panic("Can't find symbol: " + err.Error())
}
awesomeFactory := sym.(func() *myplugin.MyPlugin)
awesome := awesomeFactory()
println("Loaded " + awesome.Name + " plugin")
err = awesome.Enable()
if err != nil {
panic("Can't enable plugin: " + err.Error())
}
// Do some stuff
err = awesome.Disable()
if err != nil {
panic("Can't enable plugin: " + err.Error())
}
在运行之前,插件中的代码会查看插件是否已启用,然后再运行其他你可能定义的函数。
然后,运行代码,我们会得到如下输出:
Loaded AwesomePlugin plugin
Enabling AwesomePlugin
Disabling AwesomePlugin
显然,你不希望在各个地方都使用 panic()
。那只是一个用于处理错误的占位符。
英文:
Go doesn't support unloading a plugin. But you can, as you suggest, disable it. Commonly a plugin would define a struct containing the information about the plugin. You might return this from a factory function with a well-known name (e.g. awesome.so
contains AwesomePlugin
). One of the items you could include in the struct would be a method to disable access to the plugin. You could do something like this:
type MyPlugin struct {
Name string
Enable func() error
Disable func() error
}
Then in the plugin itself you'd do something like this:
var (
awesomeEnabled bool
)
func AwesomePlugin() *myplugin.MyPlugin {
return &myplugin.MyPlugin{
Name: "AwesomePlugin",
Enable: func() error {
println("Enabling AwesomePlugin")
awesomeEnabled = true
return nil // or do something more complex that could error
},
Disable: func() error {
println("Disabling AwesomePlugin")
awesomeEnabled = false
return nil // or do something more complex that could error
},
}
}
Then the code to load it, enable it, and disable it would be something like:
awesomePlugin, err := plugin.Open("awesome.so")
if err != nil {
panic("Can't load plugin: " + err.Error())
}
sym, err := awesomePlugin.Lookup("AwesomePlugin")
if err != nil {
panic("Can't find symbol: " + err.Error())
}
awesomeFactory := sym.(func() *myplugin.MyPlugin)
awesome := awesomeFactory()
println("Loaded " + awesome.Name + " plugin")
err = awesome.Enable()
if err != nil {
panic("Can't enable plugin: " + err.Error())
}
// Do some stuff
err = awesome.Disable()
if err != nil {
panic("Can't enable plugin: " + err.Error())
}
You'd have the code in the plugin look to see if the plugin is enabled or not before running any other functions you might define.
Then, running it, we get output like:
Loaded AwesomePlugin plugin
Enabling AwesomePlugin
Disabling AwesomePlugin
Obviously you don't want to panic()
everywhere. That's just a placeholder for doing something with the error.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论