【问题标题】:Is it possible to dynamically load Go code?是否可以动态加载 Go 代码?
【发布时间】:2013-08-14 17:00:32
【问题描述】:

正如标题所说,我想根据仅在运行时可用的信息动态加载(或不加载)Go 包。

目标是允许用户通过添加新的本机脚本命令的自定义包来扩展程序。目前,每次我添加新命令或想要禁止某些命令时,我都需要编辑程序并重新编译,而如果我可以制作某种 dll 或类似的东西,那么我可以创建一个“导入”脚本命令来搜索和加载一个命名的命令库。

出于好奇,有问题的程序是基于自定义命令的脚本库,我用于各种事情。

我提前做了一些搜索,结果看起来不太好,但我找不到明确的否。

【问题讨论】:

  • 这是个坏主意。您不想仅仅为了舒适而创建整个包的 di
  • 这不仅仅是为了舒适,而是让我可以为那些想要它们的人提供可选的扩展,而不必将它们提供给每个人。
  • 我对那些说“你不需要这个”的人表示堆栈溢出,如果你有的话就给出答案。然后建议其他方式。很多时候,即使作者确实需要不同的东西,很多人还是从搜索中得到这个问题,正是需要这个。
  • 有没有办法在运行时动态加载其他语言的.so? CGO 只允许在程序开始时加载特定的 .so(而不是在运行时选择)。
  • 这能回答你的问题吗? Load package dynamically

标签: go


【解决方案1】:

Go 还不支持动态库。 Elias Naur 最近发布了一些补丁,但它们尚未经过审查,并且不太可能包含在 Go 1.2 中。您可以阅读 Google Groups 上的讨论:

据我所知,这是关于该主题的最新讨论。

但是还有另一种方法。您可以在单独的进程中启动插件并使用 net/rpc 包与您的主应用程序进行通信。这也允许您动态启动/停止/重新编译单独的插件,它的优点是一个坏插件不会使您的程序崩溃。 Go 擅长网络通信,你要好好利用它。

我需要编辑程序并重新编译,

您还可以考虑编写一个小脚本来监视当前目录中的更改(使用 fsnotify)并执行“go build”,然后重新启动程序。我在本地开发期间在我的一些 Web 项目中使用了这种方法,并且效果很好。我无法观察到任何编译时间,而且我切换和刷新浏览器窗口的速度非常快。在我的 Python 开发周期中,解释器必须重新启动,并且每次更改都必须重新导入所有模块(这在大型项目中可能会花费大量时间!),与 Go 相比感觉非常笨拙。

【讨论】:

  • 谢谢,我知道不支持 DLL,但我很好奇是否有新的方法可以伪造类似它们的东西。看起来 RPC 是要走的路,动态重新编译不适用于库。
  • 经过一些测试,看起来 rpc 不能满足我的需要 :( 看起来使用所有 go 代码的插件系统是不可能的。
  • 一年后:这方面的事情有发展吗?像 Milo 一样,我正在尝试在纯 go 中创建一个插件系统:-/
  • 我知道 go 1.5 会支持生成动态库,但我不确定它是否支持动态加载。有谁知道吗?
【解决方案2】:

Go 1.8 对此提供了支持。目前它还很不成熟和初级,但它终于成为可能。

Mateusz Gajewski 的 go-bind-plugin 项目可能也很有趣,因为它简化了加载插件的使用。

来自plugin package 文档:

例如,一个插件定义为

package main

// // No C code needed.
import "C"

import "fmt"

var V int

func F() { fmt.Printf("Hello, number %d\n", V) }

可以用Open函数加载,然后可以访问导出的包符号V和F

p, err := plugin.Open("plugin_name.so")
if err != nil {
    panic(err)
}
v, err := p.Lookup("V")
if err != nil {
    panic(err)
}
f, err := p.Lookup("F")
if err != nil {
    panic(err)
}
*v.(*int) = 7
f.(func())() // prints "Hello, number 7"
type Symbol interface{}

【讨论】:

    【解决方案3】:

    嗯,有一个dlopen-package for Go——所以,至少,你现在可以将你的共享库 (DLL) 加载到你的 Go 程序中......你可能不得不用 C 编写你的扩展, C++ 或其他东西,您拥有能够生成共享库的工具。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-09
      • 2021-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-15
      相关资源
      最近更新 更多