(摘) Golang的插件技术

声明:内容源自网络,版权归原作者所有。若有侵权请在网页聊天中联系我

插件技术应用场景:主程序固定,由主开发者维护。插件开放技术标准,由爱好者共同维护、添加。

例如:将开发中的语音助手的插件部份单独开放出来,供以后不断添加功能。

插件程序定义:

Init中定义正则关键词,用于匹配语音中的关键词,以及与之匹配的插件功能函数。

接下来抄一下网上关于官方插件技术的应用。1.8以上支持plugin。

网上还有一个Pingo库是可以简单实现挂件的,但2015年最后更新,且官方带的原本也不复杂,也不就暂时不考虑用它了。


//testplugin.go
package main

import (
    "fmt"
)

func init() {
    fmt.Println("world")
}

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

编译有所不同:go build -buildmode=plugin testplugin.go,将编译出so文件用于调用。

//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())()
}

再看看参数调用:

func Hello(name string){
	fmt.Println("Hello ",name)
}

#在调用中修改为:
f.(func(string))("ease")

当然以上例子还是太简单,需要增加点实际应用。

插件中调用了一个外部变量

package main

import (
	"fmt"
)

var V int

func init(){
	fmt.Println("Plugin Init1")
}

func Hello(){
	fmt.Println("Hello ",V)
}

调用时就变成了

	p1, err := plugin.Open("plugin1.so")
	if err != nil {
		panic(err)
	}

	f1, err := p1.Lookup("Hello")
	if err != nil {
		panic(err)
	}

	v, err := p1.Lookup("V")
	if err != nil {
		panic(err)
	}

	*v.(*int) = 7

	f1.(func())()	

当然还是不够的,我们使用一些复杂的数据类型

在data目录下添加data.go,用于定义结构体。

如果在各个文件中(插件文件和调用文件)分别定义相同的结构体,会出现错误:

panic: interface conversion: plugin.Symbol is *main.VS, not *main.VS (types from different scopes) 来自不同作用域的类型
type VS struct {
    Name   string
    Age    int
    School string
}
package main
  
import (
    "fmt"
    "./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)
}
package main
 
import (
    "plugin"
    "./data"
)
 
func main() {
	p2, err := plugin.Open("plugin2.so")
	CheckErr(err)

	f2, err := p2.Lookup("Hello")
	CheckErr(err)

	vs, err := p2.Lookup("Vs")
	CheckErr(err)

	*vs.(*data.VS) = data.VS{
		Name: "Ease",
		Age: 42,
		School: "know",
	}

	f2.(func())()	
}

学习了网上的例子,换我的思路了,还是为了实现文章开头的目标:语音功能及实现采用插件方式。

  1. 程序自动搜索.so扩展名的文件

  2. 所有插件文件在init中必须定义好关键词,以及对应用的功能函数名

  3. 当语音反馈文字时,分别调用插件关键词定义,看是否匹配关键词。当匹配时调用对应函数完成功能。


根据使用中发现,确实做出来的so文件比较大,比生成单一的可执行文件大。即使加了-ldflags “-s -w"也一样比较大。这是一个暂时不大的问题。

相关文章