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文件< ...
随机推荐
- ES6系列_4之扩展运算符和rest运算符
运算符可以很好的为我们解决参数和对象数组未知情况下的编程,让我们的代码更健壮和简洁. 运算符有两种:对象扩展运算符与rest运算符. 1.对象扩展( spread)运算符(...) (1)解决参数个数 ...
- Spring Boot 16 条最佳实践
Spring Boot是最流行的用于开发微服务的Java框架.在本文中,我将与你分享自2016年以来我在专业开发中使用Spring Boot所采用的最佳实践.这些内容是基于我的个人经验和一些熟知的Sp ...
- vba截屏保存
Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVa ...
- libcurl使用心得-包括下载文件不存在处理相关(转)
libcurl使用心得 Libcurl为一个免费开源的,客户端url传输库,支持FTP,FTPS,TFTP,HTTP,HTTPS,GOPHER,TELNET,DICT,FILE和LDAP,跨平台,支持 ...
- sql server2008本地连接选择windows身份验证无法登陆的解决办法
1.安装完sqlserver数据库,本地连接登录不了 解决办法:进入cmd,输入net start mssqlserver 服务启动后,再次用windows身份验证就可以登陆本地数据库了
- java.io.CharConversionException: Not an ISO 8859-1 character:
java.io.CharConversionException: Not an ISO 8859-1 character: XXX 这个问题可能是因为outputstream输出中文字造成的影响. r ...
- (4)activiti工作流引擎之uel表达式
有了前面几章,我们肯定有一定的困惑,activiti如何与实际业务整合,比如一条采购单,如何跟一个流程实例互相关联起来? 这里就需要使用到activiti启动流程实例时设置一个流程实例的busines ...
- word2vec 细节解析1
count.extend(collections.Counter(list1).most_common(2))表示:使用collections.Counter统计list1列表重单词的频数,然后使用m ...
- oracle 知识点
1.条件运算2.关联运算,子查询3.集合运算4.函数运算5.分组运算[group by](凑维度,条件,过滤,分组函数)6.行转列7.PL/SQL
- DNS BIND之rndc介绍及使用
rndc(Remote Name Domain Controllerr)是一个远程管理bind的工具,通过这个工具可以在本地或者远程了解当前服务器的运行状况,也可以对服务器进行关闭.重载.刷新缓存.增 ...