golang 动态库

目录

  • 1. golang 动态库
  • 2. golang 语言使用动态库、调用动态链接库
    • 2.1. Go 插件系统
    • 2.2. 动态加载的优劣
    • 2.3. Go 的插件系统:Plugin
    • 2.4. 插件开发原则
      • 2.4.1. 插件独立
      • 2.4.2. 使用接口类型作为边界
      • 2.4.3. Unix 模块化原则
      • 2.4.4. 版本控制
    • 2.5. 插件开发示例
      • 2.5.1. 编写插件
      • 2.5.2. 使用插件

1. golang 动态库

2. golang 语言使用动态库、调用动态链接库

2.1. Go 插件系统

通过使用插件在运行时扩展程序的功能,而无需重新编译程序,这是一个很常见的功能需求,特别是在模块化设计的程序里面,比如 Nginx 的模块系统。 在 C/C++中通过使用动态库的方式可以实现动态加载,但是 Go 直到 1.8 官方才开始支持,下面将介绍 Go 如何基于动态链接库来实现动态加载。

2.2. 动态加载的优劣

优点:

  • 动态加载,也称热加载,每次升级时不用重新编译整个工程,重新部署服务,而是添加插件时进行动态更新。这对于很多比较重型的服务来说非常重要。

缺点:

  • 带来一定的安全风险,如果一些非法模块被注入如何防范
  • 给系统带来一定的不稳定的因素,如果模块有问题,没有经过良好的测试,容易导致服务崩溃
  • 为版本管理带来了难题,特别是在微服务的今天,同一个服务,加载了不同的插件,应该怎么管理版本,插件版本应该如何管理

因此请慎重考虑,是使用动态插件还是在源码里面进行插件化。

2.3. Go 的插件系统:Plugin

从 1.8 版开始,官方提供了这种插件化的手段:plugin. 此功能使程序员可以使用动态链接库构建松散耦合的模块化程序,可以在运行时动态加载和绑定。

Go 插件是使用 -buildmode = plugin 标记编译的一个包,用于生成一个共享对象 (.so) 库文件。 Go 包中的导出的函数和变量被公开为 ELF 符号,可以使用 plugin 包在运行时查找并绑定 ELF 符号。Go 编译器能够使用 build flag -buildmode = c-shared 创建 C 风格的动态共享库。

1.8 版本插件功能只能在 Linux 上使用。 1.10 也可以在 Mac 上运行。

下面将介绍使用 Go 插件系统创建模块化软件的一些开发原则,并提供一个功能齐全的示例。

2.4. 插件开发原则

使用 Go 插件创建模块化程序需要遵循与常规 Go 软件包一样严格的软件实践。然而,插件引入了新的设计问题,因为它们的解耦性质被放大了。因此我们在设计可插拔系统时,有一些原则需要关注:

2.4.1. 插件独立

应该将插件视为与其他组件分离的独立组件。这允许插件独立于他们的消费者,并拥有自己的开发和部署生命周期。注意插件的可用性很重要,因为它有肯能为整个系统带来不稳定的因素,因此系统必须为插件集成提供一个简单的封装层,插件开发人员将系统视为黑盒,不作为所提供的合约以外的假设,从而保证插件自身的可用性。

2.4.2. 使用接口类型作为边界

Go 插件可以导出任何类型的包函数和变量。您可以设计插件来将其功能解耦为一组松散的函数。缺点是您必须单独查找和绑定每个函数符号。
然而,更为简单的方法是使用接口类型。创建导出功能的接口提供了统一简洁的交互,并具有清晰的功能划分。解析到接口的符号将提供对该功能的整个方法集的访问,而不仅仅是一个方法。

2.4.3. Unix 模块化原则

插件代码应该设计成只关注一个功能点。

2.4.4. 版本控制

插件是不透明而独立的实体,应该进行版本控制,以向用户提示其支持的功能。这里的一个建议是在命名共享对象文件时使用语义版本控制。例如,上面的文件编译插件可以命名为 eng.so.1.0.0。

2.5. 插件开发示例

我以我遇到的一个实际需求为例,在开发物联网接入组件的时候,需要动态支持物解析,下面就开发一个物解析的插件系统。

下面是项目结构,parser.go 是接口规约,main.go 是主程序,plugins 存放多个插件包

├── main.go
├── parser.go
└── plugins├── car│   └── car.go└── phone└── phone.go

2.5.1. 编写插件

  • 编写主程序接口规约:main.go
package main// Parser use to parse things
type Parser interface {
byte) (meta map[string]string, data map[string]float64, err error)
}
  • 根据接口规约编写插件:car.go
package maintype car stringfunc (c *car) Parse([]byte) (meta map[string]string, data map[string]float64, err error) {
map[string]string{"key1": "a"}
map[string]float64{"key1": 1}return meta, data, nil
}var Car car
  • 根据接口规约编写插件:phone.go
package maintype phone stringfunc (p *phone) Parse([]byte) (meta map[string]string, data map[string]float64, err error) {
map[string]string{"key1": "b"}
map[string]float64{"key1": 2}return meta, data, nil
}var Phone phone
  • 编译插件插件写完后将在 plugins 目录下编译插件:
$ cd plugins
$ go build -buildmode=plugin -o car.so car/car.go
$ go build -buildmode=plugin -o phone.so phone/phone.go

最终在 plugins 目录下会生成好我们编译好的插件:

$ ls *.so
car.so   phone.so

2.5.2. 使用插件

插件的使用很简单,大概步骤如下:

  • 用 plugin.Open() 打开插件文件
  • 用 plguin.Lookup(“Export-Variable-Name”) 查找导出的符号”Car”或者”Phone”。 请注意,符号名称与插件模块中定义的变量名称相匹配
  • 使用该变量

主程序使用插件:main.go

package mainimport (
"fmt"
"plugin"
)// Parser use to parse things
type Parser interface {
byte) (meta map[string]string, data map[string]float64, err error)
}func pa() {
"./plugins/car.so")
if err != nil {
panic(err)}"Car")
if err != nil {
panic(err)}p, ok := car.(Parser)
if ok {
byte("a"))
if err != nil {
panic(err)}
"meta: %v, data: %v \n", meta, data)}
}func pb() {
"./plugins/phone.so")
if err != nil {
panic(err)}"Phone")
if err != nil {
panic(err)}p, ok := phone.(Parser)
if ok {
byte("a"))
"meta: %v, data: %v \n", meta, data)}
}func main() {pa()pb()
}

测试是否正常运行:

$ go run main.go
meta: map[key1:a], data: map[key1:1]
meta: map[key1:b], data: map[key1:2]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/145181.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mac上配置maven

本文简述mac book上的Maven环境配置,着重讲述不同点。 1.安装 下载解压后,首先配置环境变量。编辑~/.bash_profile文件。加入如下代码: export M2_HOME/Users/jackie/tools/apache-maven-3.8.1注意:“/Users/jackie/tools/apac…

Excel-快速将公式运用到一整列

先在该列的第一个单元格里写好公式,然后单击该单元格 在图中标示的地方输入我们需要填充的单元格区域 同时按住Ctrl和Enter键,这时需要填充的单元格区域就都被选中了 然后单击一下图中公式的后面,再次按下Ctrl和Enter键,这样就完…

注册表单mvc

jsp给我们的ControllerServlet 1在哪看到我们的数据呢 2什么时候用了session,有什么用 register.jsp 获取表单的name,email formBean.name是怎么定义的 3为什么就可以formbean访问 要使用的jsp对象都在servlet里面用setAttribute定义的 request.getSession().setAttribute…

v-html命令渲染的内容,使用scoped属性的情况下,样式不起作用

v-html命令渲染的内容&#xff0c;使用scoped属性的情况下&#xff0c;样式不起作用 如&#xff1a; CSS&#xff1a; <style scoped> .question_title_text img{ display: block; height: 200px; margin: 10px auto 0 auto;} </style> HTML&#xff1a; <d…

云服务器windows service2022 部署git服务器

1 安装 下载地址gitblit 解压到你的一个目录,我这里给的是C:\gitblit 根据官网提示要下载jre or jdk7.0,这里建议使用下载jre (jdk 有时候运行出问题,或者2个都安装),自行安装java,这里不做环境配置的说明 ==================================== 进入c:\gitblit\data 目录里面…

全栈工程师必须要掌握的前端Html技能

作为一名全栈工程师&#xff0c;在日常的工作中&#xff0c;可能更侧重于后端开发&#xff0c;如&#xff1a;C#&#xff0c;Java&#xff0c;SQL &#xff0c;Python等&#xff0c;对前端的知识则不太精通。在一些比较完善的公司或者项目中&#xff0c;一般会搭配前端工程师&a…

python批量为视频添加文字水印和图片水印的程序

如题&#xff0c;代码如下&#xff0c;可设置多个图片水印及它们的移动位置 功能为&#xff1a;可以添加多个动态移动的水印&#xff0c;还可以设置水印的大小以及移动速度&#xff0c;也可以增加文字水印&#xff0c;重点是这个是批量执行的&#xff0c;可以对目录下的所有视…

SpringBoot实现IP地址归属地查询

SpringBoot实现IP地址归属地查询 功能特性 标准化的数据格式 每个 IP 数据段的 region 信息都固定了格式&#xff1a; 国家|区域|省份|城市|ISP&#xff0c;只有中国的数据绝大部分精确到了城市&#xff0c;其他国家部分数据只能定位到国家&#xff0c;后前的选项全部是 0。…

React父组件怎么调用子组件的方法

调用方法&#xff1a;1、类组件中的调用可以利用React.createRef()、ref的函数式声明或props自定义onRef属性来实现&#xff1b;2、函数组件、Hook组件中的调用可以利用useImperativeHandle或forwardRef抛出子组件ref来实现。 【程序员必备开发工具推荐】Apifox一款免费API管理…

微服务架构之路7,Nacos配置中心的Pull原理,附源码

目录 一、本地配置二、配置中心1、以Nacos为例&#xff1a;2、Pull模式3、也可以通过Nacos实现注册中心 三、配置中心提供了哪些功能四、如何操作配置中心1、配置注册2、配置反注册3、配置查看4、配置变更订阅 五、主流的微服务注册中心有哪些&#xff0c;如何选择&#xff1f;…

【开源】基于JAVA的智能停车场管理系统

项目编号&#xff1a; S 005 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S005&#xff0c;文末获取源码。} 项目编号&#xff1a;S005&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容A. 车主端功能B. 停车工作人员功能C. 系…

Kubernetes基础知识了解

一、Kubernetes简介 Kubernetes是一个轻便的和可扩展的开源平台&#xff0c;用于管理容器化应用和服务。通过Kubernetes能够进行应用的自动化部署和扩缩容。在Kubernetes中&#xff0c;会将组成应用的容器组合成一个逻辑单元以更易管理和发现。Kubernetes积累了作为Google生产…

asp.net实验管理系统VS开发sqlserver数据库web结构c#编程web网页设计

一、源码特点 asp.net 实验管理系统 是一套完善的web设计管理系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使用c#语言开发。 asp.net实验管理系统1 应用技术&am…

SELinux零知识学习十二、SELinux策略语言之客体类别和许可(6)

接前一篇文章&#xff1a;SELinux零知识学习十一、SELinux策略语言之客体类别和许可&#xff08;5&#xff09; 一、SELinux策略语言之客体类别和许可 3. 有效的客体类别 &#xff08;3&#xff09;System V IPC客体队列 与IPC有关的客体类别代表System V IPC资源。下表总结…

JavaWeb-JavaWeb中的I/O(输入/输出)

JavaWeb-JavaWeb中的I/O(输入/输出) 一、JavaWeb中的I/O(输入/输出)1.1 什么是I/O1.2 JAVA中关于I/O的类库二、磁盘的I/O2.1 磁盘I/O的工作机制2.2 磁盘的物理结构2.3 磁盘的IO过程三、Java实现访问磁盘文件四、JAVA的序列化与反序列化五、网络编程5.1 Java Socket的工作机…

在IDEA中的DeBug调试技巧

一、条件断点 循环中经常用到这个技巧&#xff0c;例如&#xff1a;遍历1个List的过程中&#xff0c;想让断点停在某个特定值。 参考上图&#xff0c;在断点的位置&#xff0c;右击断点旁边的红点&#xff0c;会出来1个界面&#xff0c;在Condition这里填写断点条件即可&#…

SSM项目初始化流程与操作概念解释-SpringBoot简化版

文章目录 1.引入概念2.导入依赖3.项目配置4.依照SpringMVC框架构建项目 1.引入概念 例如某一个XX系统&#xff0c;该系统存在前台页面&#xff08;给用户直观看或使用&#xff09;&#xff0c;和后台页面&#xff08;给管理人员调整数据和权限&#xff09;。 这二个页面都通过…

【算法】复习搜索与图论

&#x1f34e; 博客主页&#xff1a;&#x1f319;披星戴月的贾维斯 &#x1f34e; 欢迎关注&#xff1a;&#x1f44d;点赞&#x1f343;收藏&#x1f525;留言 &#x1f347;系列专栏&#xff1a;&#x1f319; 蓝桥杯 &#x1f319;请不要相信胜利就像山坡上的蒲公英一样唾手…

C++二分查找算法:规划兼职工作

题目 你打算利用空闲时间来做兼职工作赚些零花钱。 这里有 n 份兼职工作&#xff0c;每份工作预计从 startTime[i] 开始到 endTime[i] 结束&#xff0c;报酬为 profit[i]。 给你一份兼职工作表&#xff0c;包含开始时间 startTime&#xff0c;结束时间 endTime 和预计报酬 pro…

Java集合List报错,java.lang.UnsupportedOperationException

目录 一、点击Arrays.asList源码&#xff0c;一探究竟二、习惯了Arrays.asList&#xff0c;就是想用.add()添加元素&#xff0c;怎么办&#xff1f;三、又有一个同事&#xff0c;是这样写的四、重新点击Arrays.asList源码&#xff0c;一探究竟五、全是坑&#xff0c;怎么办&…