码迷,mamicode.com
首页 > 其他好文 > 详细

golang plugin的依赖问题

时间:2018-10-14 16:51:46      阅读:753      评论:0      收藏:0      [点我收藏+]

标签:time   插件   expected   port   链接   int   程序   pen   cte   

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的依赖问题

标签:time   插件   expected   port   链接   int   程序   pen   cte   

原文地址:https://www.cnblogs.com/baizx/p/9786045.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!