- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
Go 1.8 支持 Go 插件。
我创建了两个插件如下。
据我了解,该插件仅公开了 main
中的函数和变量。包裹。即 plugin.Lookup()
对于非 main
将失败变量/函数。
但是我想测试一个插件是否可以在内部调用另一个插件的方法,类似于 C++ 库如何调用另一个库。
所以我测试如下:
插件 1 github.com/vimal/testplugin
$ cat myplugin.go
package main
import "C"
import "fmt"
import help "github.com/vimal/testplugin1/plug"
func init() {
fmt.Printf("main.init invoked\n")
}
// TestPlugin
func TestPlugin() string {
return help.Help()
}
$ cat myplugin.go
package main
import "C"
func HelperFunc() string {
return "help"
}
$ cat plug/helper.go
package help
func Help() string {
return "help234"
}
main
plugin2的功能
TestPlugin()
从最后一个插件。
TestPlugin()
,输出包含
"help234"
,即调用内部函数。这个可以理解,因为两个插件都加载了,一个插件可以调用另一个插件的内部代码。
TestPlugin()
,输出包含
"help234"
,即调用内部函数。观察到与 test1 中相同的输出。或许这次的方法是从
GOPATH
找到的.
"github.com/vimal/testplugin1"
至
"github.com/vimal/junk1"
,删除plugin2,只加载plugin1,调用
TestPlugin()
.输出仍然包含
"help234"
,即调用内部函数。
go version go1.8rc3 linux/amd64
最佳答案
你并没有完全按照你的想法去做。
您的 插件 1 导入并使用一个包,即 github.com/vimal/testplugin1/plug
.这不“等于” plugin2 !
这里发生的情况是,当您构建 时插件 1 ,它的所有依赖都内置在插件文件中,包括 .../testplugin1/plug
包裹。当你加载 插件 1 ,它的所有依赖项也是从插件文件中加载的,包括 plug
包裹。在此之后,无论 的加载状态如何,它都可以工作也就不足为奇了。 plugin2 .这两个插件相互独立。-buildmode=plugin
指示编译器您要构建插件而不是独立应用程序,但这并不意味着不能包含依赖项。它们必须是,因为插件无法保证 Go 应用程序将加载它,以及 Go 应用程序将具有哪些包。因为一个可运行的应用程序也只包含来自应用程序本身明确引用的标准库的包。
保证插件将拥有它需要的一切的唯一方法,如果它还包含它的所有依赖项,包括那些来自标准库的依赖项,它就会工作。 (这就是为什么构建简单的插件会生成相对较大的文件,类似于构建简单的 Go 可执行文件会生成大文件。)
例如,很少需要添加到插件中的东西包括 Go 运行时,因为一个正在运行的将加载插件的 Go 应用程序已经运行了一个 Go 运行时。 (请注意,您只能从使用相同版本的 Go 编译的应用程序加载插件。)但除此之外,插件必须包含它需要的一切。
Go 是一种静态链接语言。一旦 Go 应用程序或插件被编译,它们就不会依赖或检查 GOPATH
的值。 ,它仅在构建它们时由 Go 工具使用。
更深入的洞察
您的主应用程序和插件可能引用同一个包(导入路径为“相同”)。在这种情况下,将只使用包的一个“实例”。
如果此通常引用的包具有“状态”,例如全局变量,则可以对此进行测试。让我们假设一个名为 mymath
的通用共享包:
package mymath
var S string
func SetS(s string) {
S = s
}
pg
的插件使用它:
package main
import (
"C"
"mymath"
"fmt"
)
func Start() {
fmt.Println("pg:mymath.S", mymath.S)
mymath.SetS("pghi")
fmt.Println("pg:mymath.S", mymath.S)
}
mymath
的主要应用程序并加载
pg
(使用它):
package main
import (
"plugin"
"mymath"
"fmt"
)
func main() {
fmt.Println("mymath.S", mymath.S)
mymath.SetS("hi")
fmt.Println("mymath.S", mymath.S)
p, err := plugin.Open("../pg/pg.so")
if err != nil {
panic(err)
}
start, err := p.Lookup("Start")
if err != nil {
panic(err)
}
start.(func())()
fmt.Println("mymath.S", mymath.S)
}
cd pg
go build -buildmode=plugin
mymath.S
mymath.S hi
pg:mymath.S hi
pg:mymath.S pghi
mymath.S pghi
mymath.S
,将其设置为
"hi"
最终。然后是插件,它打印它(我们看到主应用程序设置的值
"hi"
),然后将其更改为
"pghi"
.然后再次出现主应用程序并打印
mymath.S
,再次看到插件设置的最后一个值:
"pghi"
.
mymath
.现在,如果您继续更改
mymath
,例如重命名
myMath.SetS()
至
mymath.SetS2()
,然后更新主应用程序中的调用(到
mymath.SetS2("hi")
),无需重新构建插件,只需运行主应用程序,您将获得以下输出:
mymath.S
mymath.S hi
panic: plugin.Open: plugin was built with a different version of package mymath
goroutine 1 [running]:
main.main()
<GOPATH>/src/play/play.go:16 +0x4b5
exit status 2
mymath
包的导出标识符(和签名),仅更改实现,您也会收到上述错误;例如
func SetS(s string) { S = s + "+" }
。)
关于go - Go 插件依赖是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42218472/
我在Windows 10中使用一些简单的Powershell代码遇到了这个奇怪的问题,我认为这可能是我做错了,但我不是Powershell的天才。 我有这个: $ix = [System.Net.Dn
var urlsearch = "http://192.168.10.113:8080/collective-intellegence/StoreClicks?userid=" + userId +
我有一个非常奇怪的问题,过去两天一直让我抓狂。 我有一个我试图控制的串行设备(LS 100 光度计)。使用设置了正确参数的终端(白蚁),我可以发送命令(“MES”),然后是定界符(CR LF),然后我
我目前正试图让无需注册的 COM 使用 Excel 作为客户端,使用 .NET dll 作为服务器。目前,我只是试图让概念验证工作,但遇到了麻烦。 显然,当我使用 Excel 时,我不能简单地使用与可
我开发了简单的 REST API - https://github.com/pavelpetrcz/MandaysFigu - 我的问题是在本地主机上,WildFly 16 服务器的应用程序运行正常。
我遇到了奇怪的情况 - 从 Django shell 创建一些 Mongoengine 对象是成功的,但是从 Django View 创建相同的对象看起来成功,但 MongoDB 中没有出现任何数据。
我是 flask 的新手,只编写了一个相当简单的网络应用程序——没有数据库,只是一个航类搜索 API 的前端。一切正常,但为了提高我的技能,我正在尝试使用应用程序工厂和蓝图重构我的代码。让它与 pus
我的谷歌分析 JavaScript 事件在开发者控制台中运行得很好。 但是当从外部 js 文件包含在页面上时,它们根本不起作用。由于某种原因。 例如; 下面的内容将在包含在控制台中时运行。但当包含在单
这是一本名为“Node.js 8 the Right Way”的书中的任务。你可以在下面看到它: 这是我的解决方案: 'use strict'; const zmq = require('zeromq
我正在阅读文本行,并创建其独特单词的列表(在将它们小写之后)。我可以使它与 flatMap 一起工作,但不能使它与 map 的“子”流一起工作。 flatMap 看起来更简洁和“更好”,但为什么 di
我正在编写一些 PowerShell 脚本来进行一些构建自动化。我发现 here echo $? 根据前面的语句返回真或假。我刚刚发现 echo 是 Write-Output 的别名。 写主机 $?
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 4年前关闭。 Improve thi
我将一个工作 View Controller 类从另一个项目复制到一个新项目中。我无法在新项目中加载 View 。在旧项目中我使用了presentModalViewController。在新版本中,我
我对 javascript 很陌生,所以很难看出我哪里出错了。由于某种原因,我的功能无法正常工作。任何帮助,将不胜感激。我尝试在外部 js 文件、头部/主体中使用它们,但似乎没有任何效果。错误要么出在
我正在尝试学习Flutter中的复选框。 问题是,当我想在Scaffold(body :)中使用复选框时,它正在工作。但我想在不同的地方使用它,例如ListView中的项目。 return Cente
我们当前使用的是 sleuth 2.2.3.RELEASE,我们看不到在 http header 中传递的 userId 字段没有传播。下面是我们的代码。 BaggageField REQUEST_I
我有一个组合框,其中包含一个项目,比如“a”。我想调用该组合框的 Action 监听器,仅在手动选择项目“a”完成时才调用。我也尝试过 ItemStateChanged,但它的工作原理与 Action
你能看一下照片吗?现在,一步前我执行了 this.interrupt()。您可以看到 this.isInterrupted() 为 false。我仔细观察——“这个”没有改变。它具有相同的 ID (1
我们当前使用的是 sleuth 2.2.3.RELEASE,我们看不到在 http header 中传递的 userId 字段没有传播。下面是我们的代码。 BaggageField REQUEST_I
我正在尝试在我的网站上设置一个联系表单,当有人点击发送时,就会运行一个作业,并在该作业中向所有管理员用户发送通知。不过,我在失败的工作表中不断收到此错误: Illuminate\Database\El
我是一名优秀的程序员,十分优秀!