Use hashicorp/go-plugin by defining a shared interface, implementing it in a separate plugin binary, and using the PluginSet to spawn the plugin as a child process that communicates via RPC over a Unix socket or TCP. The host application registers the plugin, starts it, and retrieves a typed client to call methods as if they were local, while the framework handles the process lifecycle and serialization automatically.
First, define the interface in a shared package that both the host and plugin import. The host registers the plugin with a unique name and a factory function that returns the interface implementation.
// shared/interface.go
package plugin
import "context"
type Greeter interface {
Greet(ctx context.Context, name string) (string, error)
}
// host/main.go
func main() {
// Register the plugin with a unique name
plugin.Serve(&plugin.ServeConfig{
HandshakeConfig: handshake,
Plugins: map[string]plugin.Plugin{
"greeter": &GreeterPlugin{},
},
})
}
The plugin binary implements the interface and registers itself using plugin.Serve. The host application uses plugin.Client to start the plugin process, wait for the handshake, and retrieve the client.
// host/client.go
func main() {
client := plugin.NewClient(&plugin.ClientConfig{
HandshakeConfig: handshake,
Plugins: map[string]plugin.Plugin{
"greeter": &GreeterPlugin{},
},
Cmd: exec.Command("./my-plugin"), // Path to the compiled plugin binary
})
// Connect to the plugin process
rpcClient, err := client.Client()
if err != nil {
log.Fatal(err)
}
defer client.Kill() // Ensures the plugin process is terminated
// Retrieve the typed interface
raw, err := rpcClient.Dispense("greeter")
if err != nil {
log.Fatal(err)
}
greeter := raw.(plugin.Greeter)
msg, err := greeter.Greet(context.Background(), "World")
if err != nil {
log.Fatal(err)
}
fmt.Println(msg)
}
Ensure the plugin binary is compiled with the same Go version as the host to avoid protocol mismatches, and always call client.Kill() or use defer to prevent orphaned processes. The framework automatically manages the RPC connection, serialization, and error propagation between the host and the child process.