golang plugin的依赖问题
Posted baizx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
",greeter.GetShareVariable())
fmt.Println("change anotherlib's variable")
anotherlib.ShareVariable=5
fmt.Printf("main share=%d,plugin share=%d
",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
",greeter.GetShareVariable())
fmt.Println("change anotherlib's variable")
anotherlib.ShareVariable=5
fmt.Printf("main share=%d,plugin share=%d
",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的依赖问题的主要内容,如果未能解决你的问题,请参考以下文章