Week 16 - Plugins: plugin, go-plugin, gRPC-Based Extensions¶
16.1 Conceptual Core¶
- Go has two plugin stories:
pluginpackage (stdlib)-load.sofiles at runtime viadlopen. Linux/macOS only; brittle in practice (every dependency must match the host's exact build, including the Go version).- HashiCorp
go-plugin-out-of-process plugins communicating via gRPC or net/rpc over a local pipe. Used by Terraform, Vault, Packer, Nomad. Robust, polyglot, version-tolerant. - For any production extensibility story today, use
go-plugin(or its design pattern)-not the stdlibpluginpackage.
16.2 Mechanical Detail¶
pluginpackage mechanics:plugin.Open("./plug.so")loads the shared object.p.Lookup("Symbol")returns aninterface{}that you type-assert.- Constraints: same Go version, same module versions of every shared dependency, same build flags. In practice, used only for narrow, controlled use cases.
go-plugindesign:- Host process spawns plugin as a subprocess.
- Plugin advertises a "magic cookie" to confirm both sides agree.
- They negotiate a protocol version and one of (gRPC, net/rpc) as the transport.
- The host calls the plugin's interface methods, which round-trip over the pipe.
- On host shutdown, the plugin process is killed.
- Versioning: declare a
HandshakeConfigand one or morePlugininterfaces per protocol version. Drop old versions on major bumps. - Performance: per-call latency is microseconds (in-process) or tens of microseconds (cross-process). Not for hot paths; use for control-plane operations (provisioning, configuration, lifecycle).
16.3 Lab-"A Pluggable Storage Backend"¶
Build a service whose storage backend is a plugin. The host defines an interface Storage { Get(key) (val, err); Put(key, val) error; Delete(key) error }. Ship two plugins: an in-memory backend, and a file-system backend. Both communicate via gRPC over go-plugin. Demonstrate hot-swap by killing one plugin process and starting the other.
16.4 Idiomatic & golangci-lint Drill¶
staticcheck SA1019(deprecatednet/rpcpatterns),gocritic: ifElseChain. Plugin code paths are often where dependency-injection mistakes accumulate; review with discipline.
16.5 Production Hardening Slice¶
- Add structured logging across the host/plugin boundary using
slogwith consistent attribute keys. Add a health-check method to every plugin interface; the host periodically probes it and ejects unhealthy plugins.
Month 4 Capstone Deliverable¶
A reflect-codegen-plugins/ workspace:
1. validator-rs (week 13)-cached reflective validator with the 10× win.
2. noctx-analyzer (week 14)-unitchecker binary, runs in CI.
3. three-gens (week 15)-stringer + mock + JSON marshaler generators.
4. pluggable-storage (week 16)-go-plugin host + two backends.
CI gates additions: custom analyzer in golangci-lint, generated-code freshness check, go-plugin integration test under - race. By end of month, open one PR upstream againstgolangci-lint(a small custom-analyzer doc fix is sufficient) orgo-playground/validator` (a benchmark, a doc, anything).