weima
weima

Reputation: 4912

golang: how to unload an already loaded "go plugin" 1.8

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?

Upvotes: 2

Views: 2878

Answers (1)

relistan
relistan

Reputation: 381

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.

Upvotes: 1

Related Questions