Plugin库介绍
Package plugin implements loading and symbol resolution of Go plugins.
A plugin is a Go main package with exported functions and variables that has been built with:
go build -buildmode=plugin
When a plugin is first opened, the init functions of all packages not already part of the program are called. The main function is not run. A plugin is only initialized once, and cannot be closed.
Currently plugins are only supported on Linux, FreeBSD, and macOS. Please report any issues.
type Plugin
func Open(path string) (*Plugin, error)
func (p *Plugin) Lookup(symName string) (Symbol, error)
type Symbol
通过概览,了解到这个库提供了插件化开发的模式,符合unix设计哲学。
使用
废话不多说,先撸起代码:
写一个plugin的源文件:
然后写一个主程序:
/**
* @file main.go
* @brief 主程序入口
* @author DongChaofeng <s654632396@hotmail.com>
* @version 0.0.1
* @date 2021-07-14
*/
package main
import (
"fmt"
"os"
"plugin"
)
// Plugins 全局插件变量
var Plugins map[string]*plugin.Plugin
/**
* @brief init 程序初始化
*
* @return
*/
func init() {
fmt.Println("main initialize..")
fmt.Println("init Plugins Mapper...")
// 初始化我们的全局插件变量mapper
Plugins = make(map[string]*plugin.Plugin)
// 调用加载插件的函数
if err := loadPlugs(); err != nil {
fmt.Errorf("[loading plugins] %s\n", err)
os.Exit(1)
}
}
/**
* @brief loadPlugs 加载默认so插件的函数
*
* @param
*
* @return error
*/
func loadPlugs() (err error) {
// 从本地加载动态链接库, 注册到全局插件变量里
Plugins["plug_1"], err = plugin.Open("./plug_1.so")
if err != nil {
return err
}
fmt.Println("plugs loaded.")
return
}
func main() {
// 使用Lookup函数,从 plug_1 这个so库中查找 TestPlug 这个symbol
funcTest, err := Plugins["plug_1"].Lookup("TestPlug")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// 然后使用断言, 断言这个symbol的类型, 这里是断言的 type func(string)
if PfuncTestPlug, ok := funcTest.(func(string)); ok {
// 现在可以调用函数了
PfuncTestPlug("abc")
}
}
编写我们的makefile
BUILD_PATH?=build
MAIN_OUTPUT_FILE=test
MAIN_PROGRAM=${BUILD_PATH}/${MAIN_OUTPUT_FILE}
# make run
run: plug_1.so
go build -o=${MAIN_PROGRAM} main.go
[ -f "${MAIN_PROGRAM}" ] && cd ${BUILD_PATH} && sh -c ./${MAIN_OUTPUT_FILE}; cd -
plug_1.so: clean
go build -buildmode=plugin -o=${BUILD_PATH}/plug_1.so plug_1.go
pre_build:
([ ! -d "${BUILD_PATH}" ] && mkdir ${BUILD_PATH}) || echo "ok."
clean: pre_build
[ -d "${BUILD_PATH}" ] && rm -rf ${BUILD_PATH}/{*.so,${MAIN_OUTPUT_FILE}}
.Phony: run clean pre_build
好,现在目录如下:
执行
完美运行!