Golang 中实现动态代理

devtools/2024/9/19 18:55:33/ 标签: golang, 开发语言, 后端, 设计模式, 代理模式

在 Go 语言中,没有像 Java 中那样直接支持的动态代理机制,因为 Go 是静态类型的编程语言,不支持像 Java 反射那样基于接口的动态代理。但我们可以通过组合使用反射(reflect 包)和高阶函数的方式,实现类似于动态代理的功能。

Go 实现“动态代理”的思路:

  1. 使用接口:定义一个接口,它是你希望代理的对象实现的接口。
  2. 使用高阶函数:定义代理函数,接收一个实际对象,并在函数调用前后执行代理逻辑。
  3. 使用反射:通过 reflect 包可以动态地调用实际对象的方法。

示例:通过高阶函数实现简单的动态代理

1. 定义接口和实现类

package mainimport "fmt"// 定义一个接口
type MyService interface {PerformAction()
}// 定义接口的实现类
type MyServiceImpl struct{}func (s MyServiceImpl) PerformAction() {fmt.Println("Performing action in MyServiceImpl")
}

2. 定义一个代理函数

使用高阶函数来代理方法调用,在函数调用前后插入逻辑。

package mainimport ("fmt"
)// 定义代理函数
func MyServiceProxy(service MyService) MyService {return &proxy{service}
}// 定义代理结构体
type proxy struct {service MyService
}// 实现接口的方法
func (p *proxy) PerformAction() {fmt.Println("Before PerformAction")p.service.PerformAction() // 调用实际的方法fmt.Println("After PerformAction")
}

3. 使用代理对象

package mainfunc main() {// 创建实际对象myService := MyServiceImpl{}// 创建代理对象proxyService := MyServiceProxy(myService)// 调用代理对象的方法proxyService.PerformAction()
}

运行结果

Before PerformAction
Performing action in MyServiceImpl
After PerformAction

解释:

  • 高阶函数:MyServiceProxy 函数返回了一个包含实际对象的代理对象,代理对象在调用实际方法之前和之后插入了自定义逻辑。
  • 组合模式:代理对象内部持有实际的服务对象,通过调用实际服务对象的方法来执行具体业务逻辑。
  • 静态代理:虽然没有像 Java 那样的动态代理机制,但是通过这种组合和高阶函数的方式,我们可以模拟类似的代理模式

反射实现(更通用的代理方式)

如果你需要实现一个更加通用的代理方法,可以使用 Go 的 reflect 包动态调用方法:

1. 使用反射动态代理

package mainimport ("fmt""reflect"
)// 定义接口
type MyService interface {PerformAction()
}// 实现类
type MyServiceImpl struct{}func (s MyServiceImpl) PerformAction() {fmt.Println("Performing action in MyServiceImpl")
}// 代理函数,使用反射实现
func DynamicProxy(service interface{}) interface{} {serviceValue := reflect.ValueOf(service)serviceType := serviceValue.Type()proxyType := reflect.FuncOf([]reflect.Type{serviceType}, []reflect.Type{}, false)return reflect.MakeFunc(proxyType, func(args []reflect.Value) []reflect.Value {fmt.Println("Before method call")results := serviceValue.Call(args)  // 调用实际方法fmt.Println("After method call")return results}).Interface()
}func main() {myService := MyServiceImpl{}// 创建动态代理对象proxyService := DynamicProxy(myService)// 调用代理对象的方法proxyService.(MyService).PerformAction()
}

总结:

  • 高阶函数代理:比较简单,适合静态代理场景。
  • 反射代理:更通用,但由于 Go 是静态类型语言,反射在性能上不如 Java 的动态代理。

http://www.ppmy.cn/devtools/114237.html

相关文章

win10怎么配置dnat规则,访问win10的网口A ip的6443端口,映射到1.1.1.1的6443端口去

在Windows 10上配置DNAT(Destination Network Address Translation)规则,可以使用Windows自带的netsh命令来实现。以下是具体步骤: 打开命令提示符(以管理员身份运行): 按 Win X,…

python学习笔记目录

基于windows下docker安装HDDM-CSDN博客 在python中安装HDDM-CSDN博客(这个办法没安装成功)

【鸿蒙】HarmonyOS NEXT星河入门到实战9-组件化开发进阶应用状态管理

目录 1.1 创建页面 1.2 页面跳转和后退 1.3 页面栈 1.4 路由模式 1.5 路由传参 2、生命周期 3、Stage模型 3.1 目录概览 3.2 app.json5应用配置 3.3 module.json5模型配置 3.4 UIAbility组件 3.5 UIAbility的添加和设置启动 3.6 UIAbility组件的生命周期 3.7 拉起另…

RT-DETR改进策略:BackBone改进|Swin Transformer,最强主干改进RT-DETR

摘要 在深度学习与计算机视觉领域,Swin Transformer作为一种强大的视觉Transformer架构,以其卓越的特征提取能力和自注意力机制,正逐步引领着图像识别与检测技术的革新。近期,我们成功地将Swin Transformer引入并深度整合至RT-DERT(一种高效的实时目标检测与识别框架)中…

硬件工程师笔试面试——无线通讯模块

目录 15、无线通讯模块 15.1 基础 无线通讯模块实物图 15.1.1 概念 15.1.2 常见的无线通讯模块及其特点 15.1.3 无线通讯模块参数 15.1.4 无线通讯模块工作原理 15.2 相关问题 15.2.1 如何根据项目需求选择合适的无线通讯模块? 15.2.2 无线通讯模块的安全性如何,如…

针对Docker容器的可视化管理工具—DockerUI

目录 ⛳️推荐 前言 1. 安装部署DockerUI 2. 安装cpolar内网穿透 3. 配置DockerUI公网访问地址 4. 公网远程访问DockerUI 5. 固定DockerUI公网地址 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下…

C++(Qt)软件调试---断点高级用法(20)

C(Qt)软件调试—断点高级用法(20) 文章目录 C(Qt)软件调试---断点高级用法(20)[toc]1、概述2、断点高级用法1.1 条件断点1.2 日志断点/记录点/消息追踪点1.3 函数断点1.4 命中次数断点1.5 异常断点1.6 等待断点/触发断点1.7 临时断…

爬虫逆向学习(六):补环境过某数四代

声明:本篇文章内容是整理并分享在学习网上各位大佬的优秀知识后的实战与踩坑记录 引用博客: https://blog.csdn.net/shayuchaor/article/details/103629294 https://blog.csdn.net/qq_36291294/article/details/128600583 https://blog.csdn.net/weixin_…

活动系统开发之采用设计模式与非设计模式的区别-后台功能总结

1、数据库ER图 2、后台功能字段 题目功能字段 数据列表 编号题目名称选项数量状态 1启用0禁用创建时间修改时间保存 题目名称选项集 选项内容是否正确答案 1正确0错误启禁用删除素材图库功能字段 数据列表 编号原文件名称文件类型文件大小加密后文件名文件具体路径上传类型状态…

尚航科技受邀出席腾讯全球数字生态大会,并重磅发布云智算中心共建计划

近日,以“智启新机 云驱增长”为主题的2024腾讯数字生态大会在深圳国际会展中心盛大开幕!尚航科技作为特邀企业出席AI基础设施专场峰会,并做主题分享“AI时代下的智算最佳实践”的主题演讲,作为腾讯云首批合作伙伴,共同…

JavaWeb笔记整理——Redis

目录 Redis数据类型 各种数据类型的特点 Redis常用命令 字符串操作命令 哈希操作命令 列表操作命令 集合操作命令 有序集合操作命令 通用命令 在Java中操作Redis Spring Data Redis的使用方式 操作字符串类型的数据 ​编辑操作hash类型的数据 ​编辑 操作列表类…

[数据集][目标检测]红外微小目标无人机直升机飞机飞鸟检测数据集VOC+YOLO格式7559张4类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):7559 标注数量(xml文件个数):7559 标注数量(txt文件个数):7559 标注…

react native(expo)选择图片/视频并上传阿里云oss

1.引入相关库: ant-design/react-native ant风格UI库 expo-file-system 文件访问 expo-image-picker 图片/视频选择器 2.新建图片选择并上传的帮助类 import { Toast } from ant-design/react-native; import * as FileSystem from "expo-file-system"…

ubuntu安装postgreSQL

目录 1.执行更新命令 2. postgresql安装命令 ​编辑3.安装完成 4.登录postgresql命令 5.修改postgresql密码命令 6. postgreSQL密码修改完成 7.进入postgres用户 8. 进入postgresql 9.创建数据库命令 10.删除数据库 11.查看版本号 1.执行更新命令 sudo apt update…

Spring Boot-热部署问题

Spring Boot 热部署问题分析与解决方案 热部署(Hot Deployment)是指在应用程序运行过程中,无需停止应用就可以动态加载新代码、配置或资源,从而提升开发效率。在 Spring Boot 开发中,热部署是一项非常实用的功能&…

快速排序(Quick Sort)(C语言) 超详细解析!!!

生活的本质是什么呢? 无非就是你要什么就不给你什么. 而生活的智慧是什么呢? 是给你什么就用好什么. ---马斯克 索引 一. 前言二. 快速排序的概念三. 快速排序的实现1. hoare2. 挖坑法3. 前后指针法 总结 正文开始 一. 前言 接上文, 前面我们了解了插入排序, 与优化版本希尔…

进程与线程

操作系统的设计可以归结为三点: (1)以多进程形式,允许多个任务同时运行; (2)以多线程形式,允许单个任务分成不同的部分运行; (3)提供协调机制&…

iptables限制网速

1、使用hashlimit来限速 #从eth0网卡进入INPUT链数据,使用模块hashlimit 限制网速为100kb/s或2mb/s,超过限制的数据包会被DROP。OUTPUT链同理,mode为srcip,有4个mode选项: srcip(默认匹配每个源地址IP,配置指定源地址…

学习使用Docker

学习使用Docker 安装环境 windows下安装docker desktop 创建镜像 特定tomcat版本war包镜像 # FROM openjdk:8-jdk FROM dockerproxy.net/library/openjdk:8-jdk# 设置时区环境变量 ENV TZAsia/Shanghai ENV CATALINA_HOME /usr/local/tomcat ENV PATH $CATALINA_HOME/bin:…

STM32-UART配置注释

void MX_USART1_UART_Init(void) { /* USER CODE BEGIN USART1_Init 0 */ // 这里是用户代码的开始部分,可以在这里添加任何初始化之前的自定义代码 // 但在这个例子中,它是空的 /* USER CODE END USART1_Init 0 */ /* 配置USART1的硬件参数 */ …