我们知道类似 Java 等半编译半解释型语言编译生成的都是类似中间态的字节码,所以在 Java 里面我们想要实现程序工作的动态扩展,可以通过 Java 的字节码编辑技术([[动态代理#ASM]]/[[动态代理#CGLIB]]),并结合 JVM 的 [[字节码动态加载#^bc6dd8]] 实现动态修改和加载字节码。

但是 Golang 是编译型语言,编译后直接生成的是可执行文件,但是如果我们又需要在不发布版本的情况下实现程序功能的动态扩展,我们可以通过什么方式来实现呢?下面主要介绍 Golang 里面实现程序功能动态扩展的两种方式:Golang 原生插件和 go-plugin 插件。

Golang 原生插件

Golang 原生插件使用流程如下:

将代码编译成 .so 文件

package main  

const Name = "PluginName"  

func GetName() string {
return Name
}

将以上代码使用 go build -buildmode=plugin 命令即可编译成插件。

使用插件示例

func main() {
// 加载插件
open, err := plugin.Open("~/plg.so")
if err != nil {
panic(err)
}
// 查找标识符
lookup, err := open.Lookup("GetName")
if err != nil {
panic(err)
}
res := lookup.(func() string)()
fmt.Printf("%v", res)
}

原生插件的弱点

  1. 编译的 Go 版本必须完全一致 - 事实上这个插件都可以不是由同一个人编写,要求编译的 Go 版本一致显然有点要求太高了
  2. 双方依赖的公共第三方库版本必须完全一致
  3. GOPATH 也得保持一致 - 不过这一点可以在编译时候使用 trimpath 参数解决
  4. 插件加载之后无法卸载

go-plugin

鉴于 Golang 原生插件框架的问题,所以包括 Terraform、Grafana 等系统使用的是 go-plugin 这个框架。go-plugin 使用流程如下。

️ 使用的时候注意复用客户端,因为每次初始化实际上是启动了一个子进程,这样会消耗非常多的内存和 CPU 资源。

我们看 go-plugin 的使用流程,可以发现其实 go-plugin 是通过在应用内部启动一个服务端子进程,应用通过 rpc 的方式和服务端子进程进行交互来实现插件的动态加载。这样其实几乎可以作为一个编译型语言实现动态加载的通用方案,实际上不是对应用本身做了扩展,而是对应用依赖的接口做了相关的扩展。

go-plugin 的具体使用可以参考文章最后的链接。

参考

浅谈 Golang 插件机制的更多相关文章

  1. 浅谈ecmall插件机制

    插件是独立于原系统的程序模块,目的是在不修改原程序的情况下对系统进行扩展,便于修改和管理.目前web开发中大多是使用钩子形式来定义插件, 比较典型的有 wordpress, drupal系统 ecma ...

  2. 浅谈Nutch插件机制(含开发实例)

    plugin(插件)为nutch提供了一些功能强大的部件,举个例子,HtmlParser就是使用比较普遍的用来分析nutch抓取的html文件的插件. 为什么nutch要使用这样的plugin系统? ...

  3. 浅谈JVM线程调度机制及主要策略

    在之前有说过线程,应该都知道,所谓线程就是进程中的一个子任务,一个进程有多个线程.今天的话主要就是谈一谈JVM线程调度机制.我们结合线程来说,当我们在做多线程的案例时,如一个经典案例,火车站卖票. * ...

  4. 浅谈java发射机制

    目录 什么是反射 初探 初始化 类 构造函数 属性 方法 总结 思考 什么是反射 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意 ...

  5. 浅谈java反射机制

    目录 什么是反射 初探 初始化 类 构造函数 属性 方法 总结 思考 什么是反射 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意 ...

  6. 浅谈android binder机制

    binder机制 是谷歌优化在android上更适合终端的IPC(多进程通信方式),满足系统对通信方式,传输性能和安全性的要求. 特性: 1. 用驱动程序来推进进程间的通信.2. 通过共享内存来提高性 ...

  7. 浅谈Java回调机制

    像许多网上介绍回调机制的文章一样,我这里也以一个现实的例子开头:假设你公司的总经理出差前需要你帮他办件事情,这件事情你需要花些时间去做,这时候总经理肯定不能守着你做完再出差吧,于是就他告诉你他的手机号 ...

  8. 浅谈java编译机制和运行机制

    源文件和字节码的组成方式 源文件: 拓展名后跟java的文件即java的源文件. Java 源码编译由以下三个过程组成: 1.分析和输入到符号表 2.注解处理 3.语义分析和生成class文件 流程图 ...

  9. 浅谈利用同步机制解决Java中的线程安全问题

    我们知道大多数程序都不会是单线程程序,单线程程序的功能非常有限,我们假设一下所有的程序都是单线程程序,那么会带来怎样的结果呢?假如淘宝是单线程程序,一直都只能一个一个用户去访问,你要在网上买东西还得等 ...

随机推荐

  1. 第八天pyhton3 函数的返回值、作用域

    返回值 pthon函数使用return语句返回"返回值": 所有函数都有返回值,如果没有return语句,隐式调用return None: return 语句并不一定是函数的语句块 ...

  2. 关于又拍云免费cdn全网加速服务的长期评测(各种踩坑)

    原文转载自「刘悦的技术博客」 ( https://v3u.cn/a_id_128 ) 妇孺皆知,前端优化中最重要的优化手段之一就是cdn加速,所谓cdn加速就是采用更多的缓存服务器(CDN边缘节点), ...

  3. React Native环境配置、初始化项目、打包安装到手机,以及开发小知识

    1.前言 环境:Win10 + Android 已经在Windows电脑上安装好 Node(v14+).Git.Yarn. JDK(v11) javac -version javac 11.0.15. ...

  4. GS2107-WTBD 用什么软件为什么新建不了GS系列

    1.GS系列GOT必须使用官网上的新软件,资料下载-软件下载-GOT 1000 & GOT 2000 & GOT Simple 画面设计软件,下载安装后,机种选择GS系列即可. 2.在 ...

  5. Linxu用户名验证登录MySQL管理数据库

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 前情介绍: 我们都知道登录MySQL数据库时,连接层接入数据库需要经过mysql.user表中,用户名密码的验证才能登录数 ...

  6. Spring源码 15 IOC refresh方法10

    参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...

  7. Spring源码 02 项目搭建

    参考源 https://www.bilibili.com/video/BV1tR4y1F75R?spm_id_from=333.337.search-card.all.click https://ww ...

  8. 我写的蓝宝石留言本php版 v4.5

    蓝宝石留言本php版v4.5采用原生php编写,在php5.6~php7.x下调试通过.本留言本使用了utf-8编码. include/config1.php是数据库连接参数的配置文件, includ ...

  9. 【JDBC】学习路径2-编写第一个JDBC程序

    第一章:导入jar包 在未安装MySQL数据库的请务必安装,安装教程:[MySQL]从入门到掌握2-下载安装 connector/J下载地址:https://dev.mysql.com/downloa ...

  10. 记一次 .NET 某金融企业 WPF 程序卡死分析

    一:背景 1. 讲故事 前段时间遇到了一个难度比较高的 dump,经过几个小时的探索,终于给找出来了,在这里做一下整理,希望对大家有所帮助,对自己也是一个总结,好了,老规矩,上 WinDBG 说话. ...