【Golang | reflect】利用反射实现方法的调用
引言
go语言中,如果某个数据类型实现了一系列的方法,如何批量去执行呢,这时候就可以利用反射里的func (v Value) Call(in []Value) []Value 方法。
// Call calls the function v with the input arguments in.
// For example, if len(in) == 3, v.Call(in) represents the Go call v(in[0], in[1], in[2]).
// Call panics if v's Kind is not Func.
// It returns the output results as Values.
// As in Go, each input argument must be assignable to the
// type of the function's corresponding input parameter.
// If v is a variadic function, Call creates the variadic slice parameter
// itself, copying in the corresponding values.
func (v Value) Call(in []Value) []Value {v.mustBe(Func)v.mustBeExported()return v.call("Call", in)
}
Call方法实际使用时主要有以下两种调用方式:
方法1:使用reflect.Type.Method.Func.Call
package mainimport ("fmt""reflect"
)type dog struct {name string
}func (a *dog) Speak() {fmt.Println("speaking!")
}
func (a *dog) Walk() {fmt.Println("walking!")
}func (a *dog) GetName() (string, error) {fmt.Println("Getting name!")return a.name, nil
}
func main() {var tudou = &dog{name: "tudou"}// 获取reflect.TypeobjectType := reflect.TypeOf(tudou)// 批量执行方法for i := 0; i < objectType.NumMethod(); i++ {fmt.Printf("Now method: %v is being executed...\n", objectType.Method(i).Name)// Call的第一个入参对应receiver,即方法的接受者本身ret := objectType.Method(i).Func.Call([]reflect.Value{reflect.ValueOf(tudou)})fmt.Printf("The return of method: %s is %v\n\n", objectType.Method(i).Name, ret)}
}
注:
1、这里说明下,为什么使用Func调用Call时第一个入参是对应receiver本身method.Func.Call([]reflect.Value{reflect.ValueOf(tudou)})
可以看下结构体Method中Func的定义,有这么一句注释func with receiver as first argument
/** The compiler knows the exact layout of all the data structures above.* The compiler does not know about the data structures and methods below.*/// Method represents a single method.
type Method struct {...Func Value // func with receiver as first argument...
}
2、objectType.Method(i)返回的是一个Method结构体
方法2:使用reflect.Value.Method(index).Call
package mainimport ("fmt""reflect"
)type dog struct {name string
}func (a *dog) Speak() {fmt.Println("speaking!")
}func (a *dog) SetName(name string) error {fmt.Println("Setting name!")a.name = namereturn nil
}func (a *dog) GetName() (string, error) {fmt.Println("Getting name!")return a.name, nil
}func main() {var tudou = &dog{name: "tudou"}// 获取reflect.ValueobjectValue := reflect.ValueOf(tudou)// 根据方法名获取method,执行CallobjectValue.MethodByName("Speak").Call(nil)objectValue.MethodByName("SetName").Call([]reflect.Value{reflect.ValueOf("newName")})objectValue.MethodByName("GetName").Call(nil)
}
注:
1、不同于方法1,使用reflect.Value.Method直接调用Call,不需要使用receiver作为第一个入参。可以看下方法MethodByName的注释,有这么一句The arguments to a Call on the returned function should not include a receiver
// MethodByName returns a function value corresponding to the method
// of v with the given name.
// The arguments to a Call on the returned function should not include
// a receiver; the returned function will always use v as the receiver.
// It returns the zero Value if no method was found.
func (v Value) MethodByName(name string) Value {if v.typ == nil {panic(&ValueError{"reflect.Value.MethodByName", Invalid})}if v.flag&flagMethod != 0 {return Value{}}m, ok := v.typ.MethodByName(name)if !ok {return Value{}}return v.Method(m.Index)
}
2、objectValue.MethodByName("Speak")返回的是一个reflect.Value,这个跟方法1调用Method()有明显区别
3、另外值得留意的是,虽然方法2可以参考方法1的for循环批量执行method,但是reflect.Value似乎并没有直接提供方法获取每一个method的Name。但是我们可以根据Index借助reflect.Type.Method(Index).Name来获取Name,这是因为每一个method的Name和Index是一一对应的
type Method struct {// Name is the method name.Name string...Index int // index for Type.Method
}
其实,注1里的方法func (v Value) MethodByName(name string) Value 里有一段也是根据这个对应关系实现的m, ok := v.typ.MethodByName(name) ... return v.Method(m.Index),有兴趣的同学可以留意观察下
相关文章:
【Golang | reflect】利用反射实现方法的调用
引言 go语言中,如果某个数据类型实现了一系列的方法,如何批量去执行呢,这时候就可以利用反射里的func (v Value) Call(in []Value) []Value 方法。 // Call calls the function v with the input arguments in. // For example, if len(in)…...
Teleport
从官网中获取到的代码如下 App.vue <template><div class"outer"><h3>Tooltips with Vue 3 Teleport</h3><div><MyModal /></div></div> </template> <script setup> import MyModal from "./My…...
flutter与原生 相互通信实战
一、原生和flutter 通信 ios 通信类 CommonUtil.swift import Foundation import Flutterpublic class CommonUtil {public static func emitEvent(channel: FlutterMethodChannel, method: String, type: String, errCode: Int32?, errMsg: String?, data: Any?){safeMa…...
结构光相机原理
结构光相机原理...
ubuntu安装Anaconda
下载 Anaconda 进入 Ubuntu,自己新建下载路径,输入以下命令开始下载 注意,如果不是 x86_64,需要去镜像看对应的版本(https://mirrors.bfsu.edu.cn/anaconda/archive/?CM&OA) wget https://mirrors.…...
【RNA structures】RNA转录的重构和前沿测序技术
文章目录 RNA转录重建1 先简单介绍一下测序相关技术2 Map to Genome Methods2.1 Step1 Mapping reads to the genome2.2 Step2 Deal with spliced reads2.3 Step 3 Resolve individual transcripts and their expression levels 3 Align-de-novo approaches3.1 Step 1: Generat…...
4、Kafka 消费者
5.1 Kafka 消费方式 5.2 Kafka 消费者工作流程 5.2.1 消费者总体工作流程 5.2.2 消费者组原理 Consumer Group(CG):消费者组,由多个consumer组成。形成一个消费者组的条件,是所有消费者的groupid相同。 • 消费者组内…...
CSS3 渐变
CSS3 渐变可以让你在两个或多个指定的颜色之间显示平稳的过渡。 CSS3渐变有两种类型:线性渐变(Linear Gradients)和径向渐变(Radial Gradients)。 线性渐变(Linear Gradients): 线性…...
【Python 千题 —— 基础篇】分割有效信息
题目描述 题目描述 有时候我们需要截取字符串以获取有用的信息,比如对于字符串 “日期:2010-10-29”,我们需要截取后面的 10 个字符来获取日期,以便进行进一步分析。编写一个程序,输入一个字符串,然后输出…...
webrtc基于DTLS的端口复用技术
DTLS协议: DTLS(Datagram Transport Layer Security)数据包安全传输协议,用于在不可靠的数据包传输协议上(如UDP)提供数据的安全传输。 UDP多路复用: 一个UDP多路复用,被用来处理共享同一个UDP端口的多个并发的UDT连接。类似同一个tcp port上创建多个socket connec…...
【2024秋招】2023-9-20 度小满信贷系统平台部二面
1 面试官的部门介绍 我们部门是信贷系统平台部,主要是为度小满做一个服务,你应该也接触过信用卡,跟这种差不多,用户可以打进我们的系统申请一个额度,整个部门的规模大概是400-500人左右,我个人来自平台数据…...
【Django 04】Serialization 序列化的高级使用
序列化器 serializers 序列化器的作用 序列化将 queryset 和 instance 转换为 json/xml/yaml 返回给前端 反序列化与序列化则相反 定义序列化器 定义类,继承自 Serializer 通常新建一个 serializers.py 文件 撰写序列化内容 suah as 目前只支持 read_only 只…...
【前端学习】—变量类型和计算(五)
【前端学习】—变量类型和计算(五) 一、JS中使用typeof能得到哪些类型 字符串(String):表示文本数据,用单引号或双引号括起来。 数字(Number):表示数值数据,包括整数和浮点数。 布尔值(Boolean):表示真或假(true或false)的逻辑值。 空值(Null):表示一个空…...
QT中窗口自绘制效果展示
项目中需要使用QT进行窗口自绘,前期先做一下技术探索,参考相关资料代码熟悉流程。本着代码是最好的老师原则,在此记录一下。 目录 1.运行效果 2.代码结构 3.具体代码 1.运行效果 2.代码结构 3.具体代码 myspeed.pro QT core gui…...
Android Studio 直接获取Spinner的值
最近做一个小demo 使用Spinner下拉框来让用户选择地区、周数(第1-12周) 然后参考了一下别人的文章 这里引用这位博主博文: AndroidStudio使用spinner控件并添加监听(极简)_安卓spinner监听事件_天王老子来了我也不…...
渗透测试工具(3)Burpsuite
笔记目录 渗透测试工具(1)wireshark渗透测试工具(2)Nmap渗透测试工具(3)Burpsuite 1.简介 是Web应用程序测试,请求的拦截和修改,扫描web应用程序漏洞,以暴力破解登陆表单,执行会话令牌等多种的随机性检查。 (1)模块介绍 ①Intercept:用于显示和修改Ht…...
大数据之LibrA数据库系统上下电管理
系统上电 操作场景 系统管理员进行例行维护停机后需要重新启动服务器与FusionInsight LibrA集群。如果安装双机Manager,上电后HA将确定主备管理节点。系统启动完成后需要启动依赖集群运行的上层业务。 对系统的影响 系统上电完成以前集群不可用。 前提条件 获…...
Node.js、Vue的安装与使用(Linux OS)
Vue的安装与使用(Linux OS) Node.js的安装Vue的安装Vue的使用 操作系统:Ubuntu 20.04 LTS Node.js的安装 安装Node.js Node.js官方下载地址 1.选择合适的系统架构(可通过uname -m查看)版本安装 2.下载文件为tar.xz格…...
SparkSQL入门
概述 两种模式 Spark on Hive: 语法是Spark SQL语法,实际上是在IDEA上编写java叠加SQL的代码。 Hive on Spark: 只是替换了Hadoop的MR,改为了Spark的计算引擎。 发展历史 RDD > DataFrame > DataSet: 都有惰性机制,遇…...
AC修炼计划(AtCoder Regular Contest 167)
传送门:AtCoder Regular Contest 167 - AtCoder 再次感谢樱雪喵大佬的题解,讲的很详细,Orz。 大佬的博客链接如下:Atcoder Regular Contest 167 - 樱雪喵 - 博客园 (cnblogs.com) 第一题很签到,就省略掉了。 第二题…...
Windows 11 22H2 大文件传输“减速带”:SMB协议之外的排查与Robocopy提速方案
1. Windows 11 22H2文件传输减速现象解析 最近不少升级到Windows 11 22H2版本的用户都遇到了一个头疼的问题:传输大文件时速度明显变慢。我自己在迁移一个20GB的视频素材库时就深有体会,原本10分钟能完成的传输现在要花将近17分钟,效率直接打…...
Day05:大模型安全与合规科普笔记:守护AI时代的数据安全防线
文章目录大模型安全与合规科普笔记:守护 AI 时代的数据安全防线引言:AI 时代的安全挑战一、数据隐私:涉密数据的安全防护1.1 涉密及客户数据必须脱敏加密的原因1.2 严禁直接传入公共大模型的影响1.3 数据脱敏和加密的技术原理与实施方式二、内…...
SAP MM | 如何解决汇率报错及合同主数据配置?
问题背景在 SAP 系统的日常运维中,采购业务往往涉及跨国贸易或多币种结算。当我们在创建采购订单(PO)、合同(Contract)或进行发票校验时,系统如果无法找到交易日期对应的有效汇率,业务流程就会中…...
别只当开发板用!树莓派3B+变身家庭轻量NAS与下载机的完整配置指南
树莓派3B家庭NAS与下载中心实战:低成本打造私有云存储 家里闲置的树莓派3B除了跑跑小项目,还能做什么?今天我要分享的是如何把这台信用卡大小的电脑变成家庭网络存储(NAS)和下载中心。相比直接购买成品NAS设备,这套方案成本不到30…...
BitNet b1.58-2B-4T-GGUF开发者案例:基于Gradio+llama-server构建私有AI对话平台
BitNet b1.58-2B-4T-GGUF开发者案例:基于Gradiollama-server构建私有AI对话平台 1. 项目概述 BitNet b1.58-2B-4T-GGUF是一款极致高效的1.58-bit量化开源大模型,采用独特的权重三值化技术(-1, 0, 1),平均仅需1.58bit…...
在WSL2 Ubuntu 20.04上编译安装QEMU 6.2.0:一份详细的依赖清单与避坑指南
在WSL2 Ubuntu 20.04上编译安装QEMU 6.2.0:一份详细的依赖清单与避坑指南 对于需要在Windows环境下进行嵌入式或系统开发的工程师来说,WSL2提供了一个近乎原生的Linux开发环境。而QEMU作为一款功能强大的开源模拟器,能够模拟多种硬件架构&…...
008、Agent的记忆机制:短期记忆与长期存储的实现
008、Agent的记忆机制:短期记忆与长期存储的实现 你的Agent是否总是“健忘”?对话超过几轮就忘了上下文,无法处理复杂任务?本文将为你彻底解决Agent的记忆难题,构建一个能“记住过去、规划未来”的智能体。 前言 在上一篇《让Agent学会“说话”:文本生成与对话输出实战》…...
保姆级教程:用WoLF PSORT、YLoc和DeepLoc 2.0搞定蛋白质亚细胞定位预测(附结果解读)
蛋白质亚细胞定位预测实战指南:WoLF PSORT/YLoc/DeepLoc 2.0全流程解析 当你在实验室首次拿到Nanog蛋白序列时,是否曾对着满屏的预测结果感到困惑?三个工具给出了相似但不完全相同的定位建议,该相信哪一个?这份指南将…...
终极指南:如何用EverythingToolbar实现Windows文件搜索效率翻倍 [特殊字符]
终极指南:如何用EverythingToolbar实现Windows文件搜索效率翻倍 🚀 【免费下载链接】EverythingToolbar Everything integration for the Windows taskbar. 项目地址: https://gitcode.com/gh_mirrors/eve/EverythingToolbar 你是否厌倦了在Windo…...
Inspirit Capital将收购Kaplan Languages Group
专注于企业分拆业务投资的Inspirit Capital欣然宣布,计划从Kaplan手中收购全球领先的语言教育平台KLG Kaplan Languages Group (“KLG”)。本次出售的所有条件均已达成,预计交易将于5月1日完成。 KLG旗下拥有Kaplan International Languages、Alpadia L…...
