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设计哲学。
废话不多说,先撸起代码:
/** * @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") } }
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
好,现在目录如下:
完美运行!