golang plugin的依赖问题
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的依赖问题的更多相关文章
- Sublime+Golang Plugin
很喜欢在Sublime开发Golang程序,主要是要一个Sublime Golang Plugin, 可以给代码autocomplement.相当的棒! 1.安装Sublime https://www ...
- 使用Maven Assembly plugin将依赖打包进jar
一个Eclipse的工程,在pom中配置了若干依赖,需要将pom中所有的依赖全部打包进一个jar包中,可以选择的方案有maven-assembly-plugin和fatjar.以前采用fatjar进行 ...
- Golang modules包依赖管理工具
初始化 执行go mod init module-name,其中module-name为包名字,执行完后会生成go.mod文件,如下 module module-name go 1.13 包管理 使 ...
- install golang plugin in webstrom
https://github.com/go-lang-plugin-org/go-lang-idea-plugin/wiki/Documentation
- Golang 无法下载依赖 golang.org (GoLand解决方法)
如下图所示将Proxy设置为:https://goproxy.io/
- 解决vscode中golang插件依赖安装失败问题
vscode中安装ms-vscode.go插件后可以开启对go语言的支持,ms-vscode.go插件需要依赖一些工具,安装完成后提示 gocode go-outline go-symbols gur ...
- maven工程打包成runnable的jar包,拷贝资源和依赖jar包
eclipse下新建maven工程,生成runnable的jar包.之前一直是手动拷贝依赖的jar包和资源文件,烦得要死.上网可劲查了一下.解决方案如下. 在pom的配置文件中做如下配置: <b ...
- [golang学习] 在idea中code & debug
[已废弃]不需要看 idea 虽然审美倒退了n年. 不过功能还是相当好用的. idea 的go插件堪称最好的go ide. 1. 语法高亮支持 2. 智能提示 3. 跳转定义(反跳转回来) 4. 集成 ...
- 基于Maven管理的Mapreduce程序下载依赖包到LIB目录
1.Mapreduce程序需要打包作为作业提交到Hadoop集群环境运行,但是程序中有相关的依赖包,如果没有一起打包,会出现xxxxClass Not Found . 2.在pom.xml文件< ...
随机推荐
- django-admin:command not found的解决办法
django-admin:command not found的解决办法 找到django-admin的路径 绝对路径 然后用命令行运行 python3 /usr/local/python3/lib/ ...
- ADO 缓存更新
if (ADOQuery1->UpdateStatus() == usUnmodified) return; ADOQuery1->UpdateBatch(arAll); Update ...
- 使用API调用外部程序并监控程序状态
Public Type SHELLEXECUTEINFO cbSize As Long fMask As Long hwnd As Long lpVerb As String ...
- dubbo 提供者 ip不对
1.服务器多网卡绑定,导致服务起来后程序自己选择的ip不对. 2.提供服务的机器开启了vpn. 3.dubbo配置文件中写死了host. 以下为转载:转自http://www.ithao123.cn/ ...
- Go Methods and Interfaces
[Go Methods and Interfaces] 1.Go does not have classes. However, you can define methods on struct ty ...
- VMware Workstation 虚拟机的服务启动项
- C语言结合汇编开发系统内核
- MySQL学习2---索引
MySQL 索引 MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度. 索引分单列索引和组合索引.单列索引,即一个索引只包含单个列,一个表可以有多个单列索引, ...
- c++静态变量与菲静态变量
刚开始用C++写程序,遇到了一个很奇怪的问题,就是在类定义的面定义了一个静态成员变量,但在使用时编译器报错称变量不是类的成员. 文件a.h内容: /**********************A.h* ...
- Shiro和Spring 集合实现同一个账号只能一个人在线使用,其它人在使用进行剔除(八)
1.实现原理其实就是自定义过滤器,然后登录时,A登录系统后,B也登录了,这个时候获取此账号之前的session给删除,然后将新的session放入到缓存里面去,一个账户对应一个有序的集合 编写自定义过 ...