向go程序添加插件

向go程序添加插件,go,plugins,Go,Plugins,我需要为Go程序提供可插拔功能。 其思想是,第三方可以为给定路径添加功能,即 /alive映射到http://localhost:9876,或 /branding映射到http://localhost:9877等等 我首先尝试将其视为添加一个JSONconfig文件,其中每个插件都有一个条目,例如: { "Uri": "alive", "Address":"http://localhost:9876", "Handler":"github.com/user/repo/path/to/

我需要为
Go
程序提供可插拔功能。 其思想是,第三方可以为给定路径添加功能,即

/alive
映射到
http://localhost:9876
,或
/branding
映射到
http://localhost:9877
等等

我首先尝试将其视为添加一个
JSON
config文件,其中每个插件都有一个条目,例如:

{
  "Uri": "alive",
  "Address":"http://localhost:9876",
  "Handler":"github.com/user/repo/path/to/implementation"
},
尽管这明显地揭示了
Java
的思想,而且感觉对
Go
来说完全不合适,
Go
中没有类加载器的概念,加载这意味着必须使用
golang
工具中的
loader

关于如何以更独特的方式实现这一点的建议?最后,我只需要能够将URI映射到端口和实现。

编译时配置 如果您可以使用编译时配置,那么就不需要JSON(或任何其他)配置文件

您的
main
包可以导入所有相关的“插件”,并将它们的处理程序映射到适当的路径。也不需要创建多个服务器,尽管如果这更适合您(或模块)的需要,您可以这样做

运行时配置 运行时配置和插入新模块需要在运行时加载代码。该软件包支持这一点,但目前仅在linux下支持

为此,您可以使用JSON配置文件,在该文件中列出编译的插件(编译插件的路径)以及映射它们所需的路径

main
包中,您可以读取配置文件并加载插件,插件应该公开一个变量或函数,该变量或函数将返回处理流量(请求)的处理程序。出于性能原因,这比插件自己启动http服务器更好,但两者都可以工作(插件返回一个处理程序供您注册,插件启动其服务器)

请注意,也不需要将配置设置为“静态”,主应用程序也可以在运行时接收和加载新模块(例如,通过专用处理程序,它可以接收新模块的(文件)路径和映射路径,也可以选择接收二进制插件代码;但不要忘记安全性!)

注意,虽然您可以在运行时加载插件,但没有办法“卸载”插件。加载插件后,它将一直保留在内存中,直到应用程序存在

独立、多应用程序 还有第三种解决方案,您的主应用程序将充当代理。在这里,您可以将附加的“模块”作为单独的应用程序启动,在特定端口侦听localhost,主应用程序将充当代理,将传入的请求转发到在不同端口@localhost(甚至在其他主机上)侦听的其他独立应用程序

标准库为您提供了这样做的功能

这不需要加载运行时代码,因为“模块”是可以单独启动的独立应用程序。尽管如此,这还是提供了运行时配置的灵活性,而且该解决方案也适用于所有平台。此外,此设置支持在运行时关闭模块,因为您可以同样轻松地取消映射/关闭独立模块的应用程序


单独的应用程序也可以单独启动,也可以从主应用程序启动或由主应用程序启动,这两种解决方案都是可行的。

谢谢。编译时对我们不起作用——我们不知道谁可以添加插件。事实上,我之所以提出这个JSON配置,是因为到目前为止,已经提出了像http handler/alive:localhost:9876这样的cmd行参数,我不太喜欢它,因为它使cmd行在启动程序时非常庞大。我将按照你的建议探索“运行时”和“多应用”,看起来不错,再次感谢!关于命令行参数,虽然在这种情况下您可能已经离开了它,但在将来类似的情况下,可能值得一看。它允许您将所有这些配置标志放在启动时加载的ini文件中,而不是在命令行上提供它们(尽管您也可以在命令行上提供它们中的任何一个,并且CLI中提供的标志将覆盖ini中的同一标志)。为什么需要映射到端口和实现?如果代理请求,则只需要端口;如果在进程内转发请求,则不需要端口。你到底想实现什么?@Adrian该项目已经有一个Web服务器在运行,但由于其特定的路由处理无法扩展。因此,对于一些额外的功能请求,客户用他的话来说:“…[解决方案]足够灵活,不同的人可以在他们的安装上有不同的活动/品牌页面,而不需要使用完整的代码库。”好的。。。如果他们在端口上公开服务器,那么您不需要任何类型的“插件”,只需要配置映射路由->端口(像代理)。如果他们不公开端口,而是公开Go插件(共享库),那么您就不需要端口。除非您打算让应用程序在运行时从源代码下载并构建包,否则包的路径不会对您有多大好处—这是一个奇怪的用例,需要在生产环境中的部署环境中安装Go工具链。@Adrian非常感谢—我想这条评论最终帮助我更好地理解了它的用途实际上被问到了。我需要一个“默认”实现—我们的—只需检查是否有人为特定路由提供了外部服务器/端口。如果提供了代理请求,则使用默认实现,如果没有,则使用默认实现。不需要“插件”。