下面我們通過一些demo來看看如何使用golang plugin功能
入門
下面是一個簡單的plugin 代碼:
package main
// // No C code needed.
import "C"
import (
"fmt"
)
var V int
func F() { fmt.Printf("Hello, number %d\n", V) }
這是官方提供的例子,以后我們再慢慢擴展。
go build -buildmode=plugin main.go //main.go是plugin文件名稱,你可以改成其它名
你會看到多出一個main.so動態庫。
然后我們開始調用這個動態庫
package main
import (
"plugin"
)
func main() {
p, err := plugin.Open("main.so")
if err != nil {
panic(err)
}
v, err := p.Lookup("V")
if err != nil {
panic(err)
}
f, err := p.Lookup("F")
if err != nil {
panic(err)
}
*v.(*int) = 7
f.(func())()
正常編譯這個go文件,然后執行它就可以看到屏幕會輸出
Hello, number 7
這只是最簡單的形式,下面我們增加一些難度,使用一些復雜數據類型。
使用復雜類型
我們自定義一個結構體
package data
type VS struct {
Name string
Age int
School string
}
這里需要注意,必須要把結構體放到另外一個package中,否則build plugin時,會抱結構體找不到。
然后我們開始修改plugin代碼
package main
// // No C code needed.
import "C"
import (
"fmt"
"temp/data"
)
var V int
func F() { fmt.Printf("Hello, number %d\n", V) }
var Vs data.VS
func ComplexType() {
fmt.Println(Vs.Name, Vs.Age, Vs.School)
}
我們聲明了VS結構體,然后增加了一個函數用來使用結構體(需要重新編譯plugin)。 調用方也需要同步修改
package main
import (
"plugin"
"temp/data"
)
func main() {
p, err := plugin.Open("main.so")
if err != nil {
panic(err)
}
v, err := p.Lookup("V")
if err != nil {
panic(err)
}
f, err := p.Lookup("F")
if err != nil {
panic(err)
}
*v.(*int) = 7
f.(func())() // prints "Hello, number 7"
vs, err := p.Lookup("Vs")
if err != nil {
panic(err)
}
ct, err := p.Lookup("ComplexType")
if err != nil {
panic(err)
}
*vs.(*data.VS) = data.VS{
Name: "DATA",
Age: 11,
School: "BEIDA",
}
ct.(func())()
}
在main中我們構建了一個VS結構體,然后給各個屬性賦值。 如果正常,你將看到如下的信息
Hello, number 7
DATA 11 BEIDA
到此為止,我們已經可以在Plugin中使用高級復雜結構體了,可以說已經滿足50%需求了。 但探索無止境,如果調用和Plugin之間需要互相通訊怎么辦?下面我們看看Plugin是否支持Chan。
支持Chan
首先聲明一個全局Chan
package data
type VS struct {
Name string
Age int
School string
}
var Msg = make(chan VS)
不但聲明了一個全局chan,而且是高級類型的chan。 下面在Plugin中使用chan
package main
// // No C code needed.
import "C"
import (
"fmt"
"temp/data"
)
var V int
func F() { fmt.Printf("Hello, number %d\n", V) }
var Vs data.VS
func ComplexType() {
fmt.Println(Vs.Name, Vs.Age, Vs.School)
Vs.Age = Vs.Age * 4
data.Msg <- Vs
}
Plugin接收到vs數據后,將AGE放大4倍在扔出去(扔哪里就不管了)(需要重新編譯plugin)。 再修改一下調用函數:
package main
import (
"plugin"
"temp/data"
)
func main() {
p, err := plugin.Open("main.so")
if err != nil {
panic(err)
}
v, err := p.Lookup("V")
if err != nil {
panic(err)
}
f, err := p.Lookup("F")
if err != nil {
panic(err)
}
*v.(*int) = 7
f.(func())() // prints "Hello, number 7"
vs, err := p.Lookup("Vs")
if err != nil {
panic(err)
}
ct, err := p.Lookup("ComplexType")
if err != nil {
panic(err)
}
*vs.(*data.VS) = data.VS{
Name: "DATA",
Age: 11,
School: "BEIDA",
}
go ct.(func())()
select {
case m := <-data.Msg:
println(m.Age)
}
}
其實是在main函數中接受扔回來的VS結構體。 編譯之后再執行,可以看到
Hello, number 7
DATA 11 BEIDA
44
posted on 2017-01-19 18:44
思月行云 閱讀(2402)
評論(0) 編輯 收藏 引用 所屬分類:
Golang