golang以插件的方式加載golang動態庫

環境

系統: linux (別問爲什麼,因爲windows下golang不支持動態庫)
golang版本: 1.5 以上支持動態庫,1.8以上支持plugin

插件代碼

插件代碼跟普通的golang模塊代碼沒啥差別,主要是package必須是 main。下面是一段簡易的插件代碼

//testplugin.go
package main

import (
    "fmt"
)

func init() {
    fmt.Println("world")
    //我們還可以做其他更高階的事情,比如 platform.RegisterPlugin({"func": Hello}) 之類的,向插件平臺自動註冊該插件的函數
}

func Hello() {
    fmt.Println("hello")
}

init 函數的目的是在插件模塊加載的時候自動執行一些我們要做的事情,比如:自動將方法和類型註冊到插件平臺、輸出插件信息等等。

Hello 函數則是我們需要在調用方顯式查找的symbol

編譯命令

go build -buildmode=plugin testplugin.go

編譯完後我們可以看到當前目錄下有一個 testplugin.so 文件
我們也可以通過類似如下命令來生成不同版本的插件

go build -o testplugin_v1.so -buildmode=plugin testplugin.go

如果要想更好的控制插件的版本,想做更酷的事情,比如:熱更新插件。那麼可以採用自動註冊的方式,新版本的插件加載上來後,自動註冊插件版本號,插件平臺裏優先使用新版本的方法。

使用

使用方需要引入 plugin 這個包

//main.go
package main

import (
    "plugin"
)

func main() {
    p, err := plugin.Open("testplugin.so")
    if err != nil {
        panic(err)
    }   
    f, err := p.Lookup("Hello")
    if err != nil {
        panic(err)
    }   
    f.(func())()
}

輸出

$ go run main.go 
world
hello

我們可以看到,我們只顯式調用了插件中的Hello方法,打印hello這個字符串,但是在調用Hello之前,已經輸出了world,這個正是插件init函數做的事情。

總結

golang支持插件使得golang程序的擴展性上升到另一個臺階,可以用來做更酷的事情,如:利用插件做服務的熱更新

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章