我们知道类似 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. 【高并发】通过源码深度分析线程池中Worker线程的执行流程

    大家好,我是冰河~~ 在<高并发之--通过ThreadPoolExecutor类的源码深度解析线程池执行任务的核心流程>一文中我们深度分析了线程池执行任务的核心流程,在ThreadPool ...

  2. 新型MPP的Doris数据库:数据模型和数据分区使用详解

    Apache Doris是一个现代化的MPP分析性数据库产品.是一个由百度开源,在2018年贡献给Apache基金会,成为有顶级开源项目.仅需要亚秒级响应时间即可获得查询结果,可以有效地支持实时数据分 ...

  3. SQL注入 基础学习

    SQL注入学习笔记 注入原理 SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有 ...

  4. electron 应用开发优秀实践

    vivo 互联网前端团队-Yang Kun 一.背景 在团队中,我们因业务发展,需要用到桌面端技术,如离线可用.调用桌面系统能力.什么是桌面端开发?一句话概括就是:以 Windows .macOS 和 ...

  5. CF708C Centroids(树形DP)

    发现变重心就是往重心上割,所以\(\text{up and down}\),一遍统计子树最大\(size\),一遍最优割子树,\(down\),\(up\)出信息,最后\(DFS\)出可行解 #inc ...

  6. LuoguP1016 旅行家的预算 (贪心)

    胡一个错误代码都能有75pts 忘了怎么手写deque其实是懒 #include <cstdio> #include <iostream> #include <cstri ...

  7. Spring Boot部署方法

    Spring Boot部署方法     网上搜到的部署方法无非是打成jar包,然后shell执行nohup java调用jar命令,或者是打成war包然后部署到tomcat或者jetty容器上面. S ...

  8. ADO.NET数据库开发

    ADO.NET博客  ADO.NET - 张果 - 博客园 (cnblogs.com) ADO.NET官方 ADO.NET | Microsoft Docs EntityFrameWork 开始使用 ...

  9. RabbitMQ协议-AMQP 0-9-1 (高级消息队列协议)

    工作模型 producer:生产者 Connection:TCP长连接,AMQP 0-9-1 连接通常是长期存在的.AMQP 0-9-1 是一个应用层协议,它使用 TCP 进行可靠传输.连接使用身份验 ...

  10. 洛谷P4135 作诗(不一样的分块)

    题面 给定一个长度为 n n n 的整数序列 A A A ,序列中每个数在 [ 1 , c ] [1,c] [1,c] 范围内.有 m m m 次询问,每次询问查询一个区间 [ l , r ] [l, ...