动态加载软件包

49

在运行时加载特定的软件包是否可行? 我想拥有一种插件,每个插件都具有与其他插件相同的功能,但具有不同的行为,并且根据配置文件的设置加载其中一个或另一个插件。

5个回答

40

不,Go语言不支持动态加载库。

最好的选择是将插件作为独立可执行文件启动,并通过套接字或stdin/stdout进行通信。

2017更新

这个答案现在已经不正确了,Go现在支持插件(截至2021年6月仅适用于Linux和MacOS)


但是这样,如果不知道将使用哪个包,我该如何在第一次加载时加载包呢? - Pepeluis
4
截至Go 1.8,仍然只能在Linux上运行。 - user2679859
1
好的,Linux和OSX。 - OneOfOne
1
它还不够稳定!插件支持目前还不完整,仅支持Linux,并且已知存在一些bug。请报告任何问题。 - Aaron

27

19
你可以考虑在运行时执行“插件”包,通过编写一个新程序(例如,到临时目录)并通过exec.Command执行,类似于exec.Command("go", "run", files…).Run() 在这里可以看到一些类似的代码here

你好,谢谢,它可以解决我的问题,我能够同时与ZeroMQ或类似的工具进行通信。 - Pepeluis
4
我通过独立构建几个插件来实现“动态加载”,这些插件必须支持从标准输入读取数据。在 main.go 中,我从配置文件中读取插件列表,然后使用 exec.Command 启动每个插件(在 go 协程中),然后我可以向插件的 StdinPipe 写入数据,每个插件都可以读取到数据。 - zhaozhi

0

只需要这样做,创建一个代码生成器来读取配置文件,在按顺序加载包的基本go文件中生成代码,然后执行它。编译型语言无法提供动态加载,甚至Dart也有点受苦,简单地读取配置文件,然后创建一个临时文件,其中包含必要的代码以加载并与套接字或HTTP通信。


3
“编译语言不能提供动态加载” - C/C++是编译语言,但它们通过 'dlopen' 提供此功能。几乎所有语言都提供某种形式的动态加载,除了Go语言。 - Petar
1
现在,Go语言有一个dlopen包,可以使用共享库。如何生成这些库以及是否可以将Go代码转换为库是两个不同的问题... - Mikhail T.

-4

我认为你正在寻找的是特殊函数init

如果你添加一个

func init() {

}

在一个包内,它将在第一次导入该包时运行。这仅在同一二进制文件中发生。正如其他人已经说过的那样,Go不支持动态加载库。


1
init 的问题在于,在读取配置文件之前,我不知道应该加载哪个包。因此,如果我无法动态加载包,那么 init 的方式就不是解决方案。 - Pepeluis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接