浅谈 Golang 插件机制
2022/10/5 4:23:55
本文主要是介绍浅谈 Golang 插件机制,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
我们知道类似 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) }
原生插件的弱点
- 编译的 Go 版本必须完全一致 - 事实上这个插件都可以不是由同一个人编写,要求编译的 Go 版本一致显然有点要求太高了
- 双方依赖的公共第三方库版本必须完全一致
- GOPATH 也得保持一致 - 不过这一点可以在编译时候使用 trimpath 参数解决
- 插件加载之后无法卸载
go-plugin
鉴于 Golang 原生插件框架的问题,所以包括 Terraform、Grafana 等系统使用的是 go-plugin 这个框架。go-plugin 使用流程如下。
⚠️ 使用的时候注意复用客户端,因为每次初始化实际上是启动了一个子进程,这样会消耗非常多的内存和 CPU 资源。
我们看 go-plugin 的使用流程,可以发现其实 go-plugin 是通过在应用内部启动一个服务端子进程,应用通过 rpc 的方式和服务端子进程进行交互来实现插件的动态加载。这样其实几乎可以作为一个编译型语言实现动态加载的通用方案,实际上不是对应用本身做了扩展,而是对应用依赖的接口做了相关的扩展。
go-plugin 的具体使用可以参考文章最后的链接。
参考
- 使用 Go Plugin 实现插件化编程
- 基于 RPC 实现的 Go 插件机制
这篇关于浅谈 Golang 插件机制的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-20go-zero 框架的 RPC 服务 启动start和停止 底层是怎么实现的?-icode9专业技术文章分享
- 2024-12-19Go-Zero 框架的 RPC 服务启动和停止的基本机制和过程是怎么实现的?-icode9专业技术文章分享
- 2024-12-18怎么在golang中使用gRPC测试mock数据?-icode9专业技术文章分享
- 2024-12-15掌握PageRank算法核心!你离Google优化高手只差一步!
- 2024-12-15GORM 中的标签 gorm:"index"是什么?-icode9专业技术文章分享
- 2024-12-11怎么在 Go 语言中获取 Open vSwitch (OVS) 的桥接信息(Bridge)?-icode9专业技术文章分享
- 2024-12-11怎么用Go 语言的库来与 Open vSwitch 进行交互?-icode9专业技术文章分享
- 2024-12-11怎么在 go-zero 项目中发送阿里云短信?-icode9专业技术文章分享
- 2024-12-11怎么使用阿里云 Go SDK (alibaba-cloud-sdk-go) 发送短信?-icode9专业技术文章分享
- 2024-12-10搭建个人博客网站之一、使用hugo创建个人博客网站