• 【学习笔记】 golang的插件 创建share object


    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的源文件:

    plug_01.go

    然后写一个主程序:

    /**
    * @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
    ", 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}
    
    .Phony: run clean pre_build
    

    好,现在目录如下:

    执行


    完美运行!

    源码

    参考阅读

  • 相关阅读:
    Java的几种常用设计模式
    面向切面编程AOP
    面向过程编程、面向对象编程
    Java基础之集合与泛型
    Spring mvc中自定义拦截器
    Hibernate框架hibernate.cfg.xml配置文件,配置自动生成表结构策略。
    Notepad++打开xml文件显示crlf的问题
    java框架
    潜龙博客地址
    联通
  • 原文地址:https://www.cnblogs.com/xiangcaiduoyidian/p/15013090.html
Copyright © 2020-2023  润新知