浅谈 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-11-15SendGrid 的 Go 客户端库怎么实现同时向多个邮箱发送邮件?-icode9专业技术文章分享
- 2024-11-15SendGrid 的 Go 客户端库怎么设置header 和 标签tag 呢?-icode9专业技术文章分享
- 2024-11-12Cargo deny安装指路
- 2024-11-02MongoDB项目实战:从入门到初级应用
- 2024-11-01随时随地一键转录,Google Cloud 新模型 Chirp 2 让语音识别更上一层楼
- 2024-10-25Google Cloud动手实验详解:如何在Cloud Run上开发无服务器应用
- 2024-10-24AI ?先驱齐聚 BAAI 2024,发布大规模语言、多模态、具身、生物计算以及 FlagOpen 2.0 等 AI 模型创新成果。
- 2024-10-20goland工具下,如修改一个项目的标准库SDK的版本-icode9专业技术文章分享
- 2024-10-17Go学习:初学者的简单教程
- 2024-10-17Go学习:新手入门完全指南