golang plugin的依赖问题

此文中涉及的plugin运行环境为mac 10.14,go版本为1.11

主要是想讨论一下插件依赖的第三方库的问题.

例子是在https://github.com/vladimirvivien/go-plugin-example一文基础之上.

简单插件

1.主程序

package main

import (
"fmt"
"os"
"plugin"
) type Greeter interface {
Greet()
} func main() {
// load module
// 1. open the so file to load the symbols
plug, err := plugin.Open("./eng/eng.so")
if err != nil {
fmt.Println(err)
os.Exit(1)
} // 2. look up a symbol (an exported function or variable)
// in this case, variable Greeter
symGreeter, err := plug.Lookup("Greeter")
if err != nil {
fmt.Println(err)
os.Exit(1)
} // 3. Assert that loaded symbol is of a desired type
// in this case interface type Greeter (defined above)
var greeter Greeter
greeter, ok := symGreeter.(Greeter)
if !ok {
fmt.Println("unexpected type from module symbol")
os.Exit(1)
} // 4. use the module
greeter.Greet() }

2. plugin代码

package main

import "fmt"

type greeting string

func (g greeting) Greet() {
fmt.Println("Hello Universe")
} // exported
var Greeter greeting

3. plugin编译方法

go build -buildmode=plugin -o eng/eng.so eng/greeter.go

4. 运行结果

go run main.go
Hello Universe

插件与主程序依赖第三方库的问题

如果主程序和插件都依赖第三方库会有什么问题呢?他们是共享一份代码?还是完全独立的copy呢?

这就类似于c语言动态链接库的依赖,但是应该又不一样. 以实验结果说话吧.

1. 同时依赖的第三方库

package anotherlib
var ShareVariable =7

2. 运行结果

和平时常见的动态库行为一致,也就是说主程序和插件共享了一份运行代码,也共享了一份运行变量.

引入了vendor的问题

实际项目中,可能代码都会使用vendor来管理自己的第三方依赖库.

这时候就会出现不一致的情况.也就是说因为主程序使用了vendor或者插件使用了vendor,

那么这时候go runtime就会认为插件和主程序用的不是同一个第三方依赖库,这时候就会出现和预期不一致的情况.

完整的代码

我已经把代码放在github,刚兴趣可以下载运行,

main.go

package main

import (
"fmt"
"os"
"plugin"
"github.com/nkbai/blog/goplugin/anotherlib"
) type Greeter interface {
Greet()
GetShareVariable() int
} func main() {
// load module
// 1. open the so file to load the symbols
plug, err := plugin.Open("./eng/eng.so")
if err != nil {
fmt.Println(err)
os.Exit(1)
} // 2. look up a symbol (an exported function or variable)
// in this case, variable Greeter
symGreeter, err := plug.Lookup("Greeter")
if err != nil {
fmt.Println(err)
os.Exit(1)
} // 3. Assert that loaded symbol is of a desired type
// in this case interface type Greeter (defined above)
var greeter Greeter
greeter, ok := symGreeter.(Greeter)
if !ok {
fmt.Println("unexpected type from module symbol")
os.Exit(1)
} // 4. use the module
greeter.Greet() fmt.Println("anotherlib in main")
fmt.Println(anotherlib.ShareVariable)
fmt.Printf("plugin anotherlib =%d\n",greeter.GetShareVariable())
fmt.Println("change anotherlib's variable")
anotherlib.ShareVariable=5
fmt.Printf("main share=%d,plugin share=%d\n",anotherlib.ShareVariable,greeter.GetShareVariable())
//可以看到输出都是5 //下面这种情况将会出现不一致的情况
testpluginvendor()
} func testpluginvendor(){
// load module
// 1. open the so file to load the symbols
plug, err := plugin.Open("pluginwithvendor/eng.so")
if err != nil {
fmt.Println(err)
os.Exit(1)
} // 2. look up a symbol (an exported function or variable)
// in this case, variable Greeter
symGreeter, err := plug.Lookup("Greeter")
if err != nil {
fmt.Println(err)
os.Exit(1)
} // 3. Assert that loaded symbol is of a desired type
// in this case interface type Greeter (defined above)
var greeter Greeter
greeter, ok := symGreeter.(Greeter)
if !ok {
fmt.Println("unexpected type from module symbol")
os.Exit(1)
} // 4. use the module
greeter.Greet()
fmt.Println("call plugin withvendor")
fmt.Println("anotherlib in main")
fmt.Println(anotherlib.ShareVariable)
fmt.Printf("plugin anotherlib =%d\n",greeter.GetShareVariable())
fmt.Println("change anotherlib's variable")
anotherlib.ShareVariable=5
fmt.Printf("main share=%d,plugin share=%d\n",anotherlib.ShareVariable,greeter.GetShareVariable())
//可以看到输出并不一致
}

plugin eng.go

package main

import "fmt"
import "github.com/nkbai/blog/goplugin/anotherlib" type greeting string func (g greeting) Greet() {
fmt.Println("Hello Universe")
}
func (g greeting) GetShareVariable() int{
return anotherlib.ShareVariable
}
// exported
var Greeter greeting

第三方依赖库 anotherlib.go

package anotherlib
var ShareVariable =7

golang plugin的依赖问题的更多相关文章

  1. Sublime+Golang Plugin

    很喜欢在Sublime开发Golang程序,主要是要一个Sublime Golang Plugin, 可以给代码autocomplement.相当的棒! 1.安装Sublime https://www ...

  2. 使用Maven Assembly plugin将依赖打包进jar

    一个Eclipse的工程,在pom中配置了若干依赖,需要将pom中所有的依赖全部打包进一个jar包中,可以选择的方案有maven-assembly-plugin和fatjar.以前采用fatjar进行 ...

  3. Golang modules包依赖管理工具

    初始化 执行go mod  init module-name,其中module-name为包名字,执行完后会生成go.mod文件,如下 module module-name go 1.13 包管理 使 ...

  4. install golang plugin in webstrom

    https://github.com/go-lang-plugin-org/go-lang-idea-plugin/wiki/Documentation

  5. Golang 无法下载依赖 golang.org (GoLand解决方法)

    如下图所示将Proxy设置为:https://goproxy.io/

  6. 解决vscode中golang插件依赖安装失败问题

    vscode中安装ms-vscode.go插件后可以开启对go语言的支持,ms-vscode.go插件需要依赖一些工具,安装完成后提示 gocode go-outline go-symbols gur ...

  7. maven工程打包成runnable的jar包,拷贝资源和依赖jar包

    eclipse下新建maven工程,生成runnable的jar包.之前一直是手动拷贝依赖的jar包和资源文件,烦得要死.上网可劲查了一下.解决方案如下. 在pom的配置文件中做如下配置: <b ...

  8. [golang学习] 在idea中code & debug

    [已废弃]不需要看 idea 虽然审美倒退了n年. 不过功能还是相当好用的. idea 的go插件堪称最好的go ide. 1. 语法高亮支持 2. 智能提示 3. 跳转定义(反跳转回来) 4. 集成 ...

  9. 基于Maven管理的Mapreduce程序下载依赖包到LIB目录

    1.Mapreduce程序需要打包作为作业提交到Hadoop集群环境运行,但是程序中有相关的依赖包,如果没有一起打包,会出现xxxxClass Not Found . 2.在pom.xml文件< ...

随机推荐

  1. OpenCL 事件的使用,以及回调函数

    ▶ 事件的两种使用方法.第一种是用事件 a 标记进入命令队列的操作 A,于是后续进入命令队列的操作 B 可以被要求等到前面事件 a 完成(即操作 A 完成)以后才能开始调度执行.第二种是使用用户自定义 ...

  2. eclipse里启动tomcat无法通过127.0.0.1访问

    在eclipse里面添加tomcat,再发布一个web项目进去,然后启动tomcat,日志显示tomcat在eclipse里面正常启动,hosts里面配置了ip跟域名的对应关系. 通过域名访问可以正常 ...

  3. Attribute与元数据

    在MSDN中,Attribute被定义为“是被指定给某一声明的一则附加的声明性信息”. 我们可以通过Attribute来定义设计层面的信息以及运行时(run-time)信息,也可以利用Attribut ...

  4. python初步要点II

    [python初步要点II] 1.is & is not 操作符用于测试2个对象是否指向同一个对象,即 id(a) == id(b). 2.整形和字符串对象是不可变对象,python会高效地缓 ...

  5. QByteArray to QString

    QByteArray => QString void BarEngine::ByteArrayToString(QByteArray &ba, QString &str) { i ...

  6. Qt Customize QVariant

    Customize QVariant #include <QCoreApplication> #include <QVariant> #include <QDebug&g ...

  7. jave 逻辑运算 vs 位运算 + Python 逻辑运算 vs 位运算

    JAVA中&&和&.||和|(短路与和逻辑与.短路或和逻辑或)的区别 博客分类: 面试题目 Java.netBlog  转自 :http://blog.csdn.net/web ...

  8. [SoapUI]怎样获取上一个Test Step的名字

    def currentStepInd = context.currentStepIndex def previousStep = testRunner.testCase.getTestStepAt(c ...

  9. Spring MVC的handlermapping之请求分发如何找到正确的Handler(RequestMappingHandlerMapping)

    这个思路同样是通过在AbstractHandlerMethodMapping里面来实现getHandlerInternal()实现自己的方法来处理寻找正确的处理器,不懂得请看上一篇. protecte ...

  10. ASP.NET 4(和ASP.NET MVC 2)中输出HTML编码的新语法<%:%>

    今天的文章介绍了ASP.NET 4中引入的一个小而且非常有用的新语法功能 - 这是在代码块中自动对输出进行HTML编码的功能.这有助于保护您的应用程序和站点免受跨站点脚本注入(XSS)和HTML注入攻 ...