当前位置: 首页 > news >正文

【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)})
可以看下结构体MethodFunc的定义,有这么一句注释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的NameIndex是一一对应的

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语言中&#xff0c;如果某个数据类型实现了一系列的方法&#xff0c;如何批量去执行呢&#xff0c;这时候就可以利用反射里的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&#xff0c;自己新建下载路径&#xff0c;输入以下命令开始下载 注意&#xff0c;如果不是 x86_64&#xff0c;需要去镜像看对应的版本&#xff08;https://mirrors.bfsu.edu.cn/anaconda/archive/?CM&OA&#xff09; 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&#xff08;CG&#xff09;&#xff1a;消费者组&#xff0c;由多个consumer组成。形成一个消费者组的条件&#xff0c;是所有消费者的groupid相同。 • 消费者组内…...

CSS3 渐变

CSS3 渐变可以让你在两个或多个指定的颜色之间显示平稳的过渡。 CSS3渐变有两种类型&#xff1a;线性渐变&#xff08;Linear Gradients&#xff09;和径向渐变&#xff08;Radial Gradients&#xff09;。 线性渐变&#xff08;Linear Gradients&#xff09;&#xff1a; 线性…...

【Python 千题 —— 基础篇】分割有效信息

题目描述 题目描述 有时候我们需要截取字符串以获取有用的信息&#xff0c;比如对于字符串 “日期&#xff1a;2010-10-29”&#xff0c;我们需要截取后面的 10 个字符来获取日期&#xff0c;以便进行进一步分析。编写一个程序&#xff0c;输入一个字符串&#xff0c;然后输出…...

webrtc基于DTLS的端口复用技术

DTLS协议: DTLS(Datagram Transport Layer Security)数据包安全传输协议,用于在不可靠的数据包传输协议上(如UDP)提供数据的安全传输。 UDP多路复用: 一个UDP多路复用&#xff0c;被用来处理共享同一个UDP端口的多个并发的UDT连接。类似同一个tcp port上创建多个socket connec…...

【2024秋招】2023-9-20 度小满信贷系统平台部二面

1 面试官的部门介绍 我们部门是信贷系统平台部&#xff0c;主要是为度小满做一个服务&#xff0c;你应该也接触过信用卡&#xff0c;跟这种差不多&#xff0c;用户可以打进我们的系统申请一个额度&#xff0c;整个部门的规模大概是400-500人左右&#xff0c;我个人来自平台数据…...

【Django 04】Serialization 序列化的高级使用

序列化器 serializers 序列化器的作用 序列化将 queryset 和 instance 转换为 json/xml/yaml 返回给前端 反序列化与序列化则相反 定义序列化器 定义类&#xff0c;继承自 Serializer 通常新建一个 serializers.py 文件 撰写序列化内容 suah as 目前只支持 read_only 只…...

【前端学习】—变量类型和计算(五)

【前端学习】—变量类型和计算(五) 一、JS中使用typeof能得到哪些类型 字符串(String):表示文本数据,用单引号或双引号括起来。 数字(Number):表示数值数据,包括整数和浮点数。 布尔值(Boolean):表示真或假(true或false)的逻辑值。 空值(Null):表示一个空…...

QT中窗口自绘制效果展示

项目中需要使用QT进行窗口自绘&#xff0c;前期先做一下技术探索&#xff0c;参考相关资料代码熟悉流程。本着代码是最好的老师原则&#xff0c;在此记录一下。 目录 1.运行效果 2.代码结构 3.具体代码 1.运行效果 2.代码结构 3.具体代码 myspeed.pro QT core gui…...

Android Studio 直接获取Spinner的值

最近做一个小demo 使用Spinner下拉框来让用户选择地区、周数&#xff08;第1-12周&#xff09; 然后参考了一下别人的文章 这里引用这位博主博文&#xff1a; AndroidStudio使用spinner控件并添加监听&#xff08;极简&#xff09;_安卓spinner监听事件_天王老子来了我也不…...

渗透测试工具(3)Burpsuite

笔记目录 渗透测试工具(1)wireshark渗透测试工具(2)Nmap渗透测试工具(3)Burpsuite 1.简介 是Web应用程序测试&#xff0c;请求的拦截和修改,扫描web应用程序漏洞,以暴力破解登陆表单,执行会话令牌等多种的随机性检查。 (1)模块介绍 ①Intercept&#xff1a;用于显示和修改Ht…...

大数据之LibrA数据库系统上下电管理

系统上电 操作场景 系统管理员进行例行维护停机后需要重新启动服务器与FusionInsight LibrA集群。如果安装双机Manager&#xff0c;上电后HA将确定主备管理节点。系统启动完成后需要启动依赖集群运行的上层业务。 对系统的影响 系统上电完成以前集群不可用。 前提条件 获…...

Node.js、Vue的安装与使用(Linux OS)

Vue的安装与使用&#xff08;Linux OS&#xff09; Node.js的安装Vue的安装Vue的使用 操作系统&#xff1a;Ubuntu 20.04 LTS Node.js的安装 安装Node.js Node.js官方下载地址 1.选择合适的系统架构&#xff08;可通过uname -m查看&#xff09;版本安装 2.下载文件为tar.xz格…...

SparkSQL入门

概述 两种模式 Spark on Hive: 语法是Spark SQL语法&#xff0c;实际上是在IDEA上编写java叠加SQL的代码。 Hive on Spark: 只是替换了Hadoop的MR&#xff0c;改为了Spark的计算引擎。 发展历史 RDD > DataFrame > DataSet&#xff1a; 都有惰性机制&#xff0c;遇…...

AC修炼计划(AtCoder Regular Contest 167)

传送门&#xff1a;AtCoder Regular Contest 167 - AtCoder 再次感谢樱雪喵大佬的题解&#xff0c;讲的很详细&#xff0c;Orz。 大佬的博客链接如下&#xff1a;Atcoder Regular Contest 167 - 樱雪喵 - 博客园 (cnblogs.com) 第一题很签到&#xff0c;就省略掉了。 第二题…...

Windows 11 22H2 大文件传输“减速带”:SMB协议之外的排查与Robocopy提速方案

1. Windows 11 22H2文件传输减速现象解析 最近不少升级到Windows 11 22H2版本的用户都遇到了一个头疼的问题&#xff1a;传输大文件时速度明显变慢。我自己在迁移一个20GB的视频素材库时就深有体会&#xff0c;原本10分钟能完成的传输现在要花将近17分钟&#xff0c;效率直接打…...

Day05:大模型安全与合规科普笔记:守护AI时代的数据安全防线

文章目录大模型安全与合规科普笔记&#xff1a;守护 AI 时代的数据安全防线引言&#xff1a;AI 时代的安全挑战一、数据隐私&#xff1a;涉密数据的安全防护1.1 涉密及客户数据必须脱敏加密的原因1.2 严禁直接传入公共大模型的影响1.3 数据脱敏和加密的技术原理与实施方式二、内…...

SAP MM | 如何解决汇率报错及合同主数据配置?

问题背景在 SAP 系统的日常运维中&#xff0c;采购业务往往涉及跨国贸易或多币种结算。当我们在创建采购订单&#xff08;PO&#xff09;、合同&#xff08;Contract&#xff09;或进行发票校验时&#xff0c;系统如果无法找到交易日期对应的有效汇率&#xff0c;业务流程就会中…...

别只当开发板用!树莓派3B+变身家庭轻量NAS与下载机的完整配置指南

树莓派3B家庭NAS与下载中心实战&#xff1a;低成本打造私有云存储 家里闲置的树莓派3B除了跑跑小项目&#xff0c;还能做什么&#xff1f;今天我要分享的是如何把这台信用卡大小的电脑变成家庭网络存储(NAS)和下载中心。相比直接购买成品NAS设备&#xff0c;这套方案成本不到30…...

BitNet b1.58-2B-4T-GGUF开发者案例:基于Gradio+llama-server构建私有AI对话平台

BitNet b1.58-2B-4T-GGUF开发者案例&#xff1a;基于Gradiollama-server构建私有AI对话平台 1. 项目概述 BitNet b1.58-2B-4T-GGUF是一款极致高效的1.58-bit量化开源大模型&#xff0c;采用独特的权重三值化技术&#xff08;-1, 0, 1&#xff09;&#xff0c;平均仅需1.58bit…...

在WSL2 Ubuntu 20.04上编译安装QEMU 6.2.0:一份详细的依赖清单与避坑指南

在WSL2 Ubuntu 20.04上编译安装QEMU 6.2.0&#xff1a;一份详细的依赖清单与避坑指南 对于需要在Windows环境下进行嵌入式或系统开发的工程师来说&#xff0c;WSL2提供了一个近乎原生的Linux开发环境。而QEMU作为一款功能强大的开源模拟器&#xff0c;能够模拟多种硬件架构&…...

008、Agent的记忆机制:短期记忆与长期存储的实现

008、Agent的记忆机制:短期记忆与长期存储的实现 你的Agent是否总是“健忘”?对话超过几轮就忘了上下文,无法处理复杂任务?本文将为你彻底解决Agent的记忆难题,构建一个能“记住过去、规划未来”的智能体。 前言 在上一篇《让Agent学会“说话”:文本生成与对话输出实战》…...

保姆级教程:用WoLF PSORT、YLoc和DeepLoc 2.0搞定蛋白质亚细胞定位预测(附结果解读)

蛋白质亚细胞定位预测实战指南&#xff1a;WoLF PSORT/YLoc/DeepLoc 2.0全流程解析 当你在实验室首次拿到Nanog蛋白序列时&#xff0c;是否曾对着满屏的预测结果感到困惑&#xff1f;三个工具给出了相似但不完全相同的定位建议&#xff0c;该相信哪一个&#xff1f;这份指南将…...

终极指南:如何用EverythingToolbar实现Windows文件搜索效率翻倍 [特殊字符]

终极指南&#xff1a;如何用EverythingToolbar实现Windows文件搜索效率翻倍 &#x1f680; 【免费下载链接】EverythingToolbar Everything integration for the Windows taskbar. 项目地址: https://gitcode.com/gh_mirrors/eve/EverythingToolbar 你是否厌倦了在Windo…...

Inspirit Capital将收购Kaplan Languages Group

专注于企业分拆业务投资的Inspirit Capital欣然宣布&#xff0c;计划从Kaplan手中收购全球领先的语言教育平台KLG Kaplan Languages Group (“KLG”)。本次出售的所有条件均已达成&#xff0c;预计交易将于5月1日完成。 KLG旗下拥有Kaplan International Languages、Alpadia L…...