See Terraform[0], Traefik[1], or OctoSQL[2].
Though I agree plugins would be welcome, especially for performance reasons, though also to be able to compile and load go code into a running go process (JIT-ish).
[0]: https://github.com/hashicorp/terraform
[1]: https://github.com/traefik/traefik
[2]: https://github.com/cube2222/octosql
Disclaimer: author of OctoSQL
And to be clear they exist, but you have to compile them with the same go version and if any dependency is shared, they need to be exactly the same version. There are also serious limitations in the sharable code
Most of the time this approach is not an issue, and it works really well. But you need to be aware that it's best to keep the number of providers in the 0-20 range per root module.
If you have a language that has a module ecosystem, compiles fast, and generates a single binary, take advantage of that; don't try to reimplement fragile dynamic linking.
Kerbal Space Program (videogame) is a big compiled executable and plugins are loaded as DLLs from a directory.
I'm not trying to reimpostare anything, I just wish it was available.
Otherwise you’re just saying “I can’t write Go like PHP” - no shit, that’s a good thing.
One way I've done it in the past is via sub processes talking via stdin/stdout. Another way I've done it is just via a regular REST API.
You'll never get enough performance for a lot of tasks if you need to pass a lot of data between applications. But depending on your needs it's more than serviceable. The benefit of this is that plugins don't need to be written in Go, as you have a simple interface.
A good example of this is something like LSP. LSP plugins are abundant and each one is written in a different language. VSCode is Typescript, the Go language server is written in Go. Both can speak to eachother fast enough.
The annoying part about the scripting language is that if something is written in Go, you want developers to also work in Go, otherwise the people writing plugins for your software, knowing better the API and use-cases, have a disconnection with the language actually used for the software, losing potential opportunities for contributions.
It's also why it can do things like generic virtual methods - it can compile an instantiation and adjust the vtable at runtime.
Perhaps you meant statically compiled binaries? Even then I'm not so sure about that. Right now I'm working on a project that statically compiles a plugin so its various libraries can't leak or be overridden by the loading application, yet which itself can load other plugins. OTOH, this is in C, C++, Objective-C, and Lua (basically C from the perspective of binary linking), all of which have mature linking semantics. (Well, at least this is true for C. Controlling symbol namespace pollution by C++ and Objective-C code requires more complexity than for C, but at least the necessary compiler and linker flags exist and are mature.)
When you use languages or toolchains that don't invest in an ABI, or which make linking too automagic (with no or little recourse for exposing various linking features a platform may offer), then runtime linking is likely to become a major limitation in some solution areas. For example, there's probably no way to coax XCode to compile my plugins properly, without outsourcing some logic to additional scripts. Ultimately a Makefile is likely the best solution--and the one I chose, anticipating these headaches--as it keeps most of the build transparent. Fortunately, XCode seems to just be a wrapper around a bunch of command-line utilities, so you don't actually need XCode at all.
I wish https://pkg.go.dev/plugin was clearly documented as not being a viable 3rd party plugin solution.
(There are also higher-level ABIs like COM, but they are usually reducible to the C ABI in practice - e.g. COM can be described entirely in terms of struct and function pointers.)