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

Golang--反射

1、概念

反射可以做什么?

  • 反射可以在运行时动态获取变量的各种信息,比如变量的类型,类别等信息
  • 如果是结构体变量,还可以获取到结构体本身的信息(包括结构体的字段、方法)
  • 通过反射,可以修改变量的值,可以调用关联的方法。
  • 使用反射,需要import("reflect")



反射相关的函数

  • reflect.TypeOf(变量名),获取变量的类型,返回reflect.Type类型(结构体类型)
  • reflect.ValueOf变量名),获取变量的值,返回reflect.Value类型(reflect.Value是一个结构体类型),通过reflect.Value,可以获取到关于该变量的很多信息。

type Type interface {// Kind返回该接口的具体分类Kind() Kind// Name返回该类型在自身包内的类型名,如果是未命名类型会返回""Name() string// PkgPath返回类型的包路径,即明确指定包的import路径,如"encoding/base64"// 如果类型为内建类型(string, error)或未命名类型(*T, struct{}, []int),会返回""PkgPath() string// 返回类型的字符串表示。该字符串可能会使用短包名(如用base64代替"encoding/base64")// 也不保证每个类型的字符串表示不同。如果要比较两个类型是否相等,请直接用Type类型比较。String() string// 返回要保存一个该类型的值需要多少字节;类似unsafe.SizeofSize() uintptr// 返回当从内存中申请一个该类型值时,会对齐的字节数Align() int// 返回当该类型作为结构体的字段时,会对齐的字节数FieldAlign() int// 如果该类型实现了u代表的接口,会返回真Implements(u Type) bool// 如果该类型的值可以直接赋值给u代表的类型,返回真AssignableTo(u Type) bool// 如该类型的值可以转换为u代表的类型,返回真ConvertibleTo(u Type) bool// 返回该类型的字位数。如果该类型的Kind不是Int、Uint、Float或Complex,会panicBits() int// 返回array类型的长度,如非数组类型将panicLen() int// 返回该类型的元素类型,如果该类型的Kind不是Array、Chan、Map、Ptr或Slice,会panicElem() Type// 返回map类型的键的类型。如非映射类型将panicKey() Type// 返回一个channel类型的方向,如非通道类型将会panicChanDir() ChanDir// 返回struct类型的字段数(匿名字段算作一个字段),如非结构体类型将panicNumField() int// 返回struct类型的第i个字段的类型,如非结构体或者i不在[0, NumField())内将会panicField(i int) StructField// 返回索引序列指定的嵌套字段的类型,// 等价于用索引中每个值链式调用本方法,如非结构体将会panicFieldByIndex(index []int) StructField// 返回该类型名为name的字段(会查找匿名字段及其子字段),// 布尔值说明是否找到,如非结构体将panicFieldByName(name string) (StructField, bool)// 返回该类型第一个字段名满足函数match的字段,布尔值说明是否找到,如非结构体将会panicFieldByNameFunc(match func(string) bool) (StructField, bool)// 如果函数类型的最后一个输入参数是"..."形式的参数,IsVariadic返回真// 如果这样,t.In(t.NumIn() - 1)返回参数的隐式的实际类型(声明类型的切片)// 如非函数类型将panicIsVariadic() bool// 返回func类型的参数个数,如果不是函数,将会panicNumIn() int// 返回func类型的第i个参数的类型,如非函数或者i不在[0, NumIn())内将会panicIn(i int) Type// 返回func类型的返回值个数,如果不是函数,将会panicNumOut() int// 返回func类型的第i个返回值的类型,如非函数或者i不在[0, NumOut())内将会panicOut(i int) Type// 返回该类型的方法集中方法的数目// 匿名字段的方法会被计算;主体类型的方法会屏蔽匿名字段的同名方法;// 匿名字段导致的歧义方法会滤除NumMethod() int// 返回该类型方法集中的第i个方法,i不在[0, NumMethod())范围内时,将导致panic// 对非接口类型T或*T,返回值的Type字段和Func字段描述方法的未绑定函数状态// 对接口类型,返回值的Type字段描述方法的签名,Func字段为nilMethod(int) Method// 根据方法名返回该类型方法集中的方法,使用一个布尔值说明是否发现该方法// 对非接口类型T或*T,返回值的Type字段和Func字段描述方法的未绑定函数状态// 对接口类型,返回值的Type字段描述方法的签名,Func字段为nilMethodByName(string) (Method, bool)// 内含隐藏或非导出方法
}

 

2、对基本数据类型反射

反射相关的函数

  • reflect.TypeOf(变量名),获取变量的类型,返回reflect.Type类型(结构体类型)
  • reflect.ValueOf变量名),获取变量的值,返回reflect.Value类型(reflect.Value是一个结构体类型),通过reflect.Value,可以获取到关于该变量的很多信息。
package mainimport("fmt""reflect"
)func testReflect(i interface{}){//1、调用TypeOf()函数,返回reflect.Type类型的变量reType := reflect.TypeOf(i)fmt.Println("reType=",reType)  //int,但不代表reType是int,只是代表reType是int的变量,reType类型是reflect.Typefmt.Printf("reType的类型是:%T\n",reType) //*reflect.Type//2、调用VauleOf()函数,返回reflect.Value类型的变量reValue := reflect.ValueOf(i)fmt.Println("reValue=",reValue) // 119,但不代表reValue是119,只是代表reValue是119的变量,reValue类型是reflect.Valuefmt.Printf("reValue的类型是:%T\n",reValue) //reflect.Value//如果想获取reValue的数值,要调用Int()方法:返回reValue持有的的数值num2 := 80 + reValue.Int() //Int()方法返回reValue持有的的数值--直接用reValue是不行的,因为reValue是reflect.Value类型的变量,类型不匹配不能直接用,需要调用Int()方法fmt.Println("num2=",num2) // 199//reValue转成空接口i2 := reValue.Interface()//类型断言n := i2.(int)n2 := n + 100fmt.Println(n2)
}func main(){//对基本数据类型进行反射//定义一个int类型的变量var num int = 119//获取变量的类型	testReflect(num)
}

3、 对结构体进行反射

与基本数据类型同理

package mainimport("fmt""reflect"
)type Student struct{Name stringAge int
}func testReflect(i interface{}){//1、调用TypeOf()函数,返回reflect.Type类型的变量reType := reflect.TypeOf(i)fmt.Println("reType=",reType) //main.Studentfmt.Printf("reType的类型是:%T\n",reType) //*reflect.rtype//2、调用VauleOf()函数,返回reflect.Value类型的变量reValue := reflect.ValueOf(i)fmt.Println("reValue=",reValue) //{张三 18}fmt.Printf("reValue的类型是:%T\n",reValue) //reflect.Value //reValue转成空接口i2 := reValue.Interface()//类型断言n,flag := i2.(Student)if flag{//断言成功fmt.Println(n.Name,' ',n.Age) // 张三 18}else{//断言失败fmt.Println("类型断言失败")}
}func main(){//对结构体数据类型进行反射//定义一个结构体类型的变量stu := Student{Name: "张三",Age: 18,}//获取变量的类型	testReflect(stu)
}

4、获取变量的类别

类型和类别的区别:

  • 类别是一个大的方向:例如不同的结构体类型都属于struct这个结构体类别
  • 类型是具体某一个类型:例如不同的结构体类型属于不同的类型
     


 

package mainimport("fmt""reflect"
)type Student struct{Name stringAge int
}func testReflect(i interface{}){//1、调用TypeOf()函数,返回reflect.Type类型的变量reType := reflect.TypeOf(i)//2、调用VauleOf()函数,返回reflect.Value类型的变量reValue := reflect.ValueOf(i)//3、获取变量的类别--Typefmt.Println("类别:",reType.Kind()) //类别:struct//4、获取变量的类别--Valuefmt.Println("类别:",reValue.Kind()) //类别:struct//获取变量的类型://reValue转成空接口i2 := reValue.Interface()//类型断言:n,flag := i2.(Student)if flag{fmt.Printf("类型:%T",n) // 类型:main.Student}
}func main(){//对结构体数据类型进行反射//定义一个结构体类型的变量stu := Student{Name: "张三",Age: 18,}//获取变量的类型	testReflect(stu)
}

 5、通过反射修改变量

package mainimport("fmt""reflect"
)type Student struct{Name stringAge int
}func testReflect(i interface{}){reValue := reflect.ValueOf(i)//通过SetInt()修改值reValue.Elem().SetInt(200)
}func main(){var num int = 100testReflect(&num) //传入的是地址,才能修改值fmt.Println(num) // 200
}

6、通过反射操作结构体的属性和方法

package main
import ("fmt""reflect"
)type Student struct{Name stringAge int
}
func (s Student) APrint(){fmt.Println("Name:",s.Name)fmt.Println("Age:",s.Age)
}func (s Student) BGetSum(n1,n2 int) int{return n1 + n2
}func (s *Student) CSet(name string,age int){s.Name = names.Age = age
}//定义函数操作结构体进行反射操作
func TestStudentReflect(a interface{}){//a转成reflect.Valueval := reflect.ValueOf(a)//通过reflect.Value类型操作结构体内部的字段:n1 := val.NumField() // 获取结构体字段的数量fmt.Println(n1)//通过遍历--获取具体的字段for i := 0; i < n1; i++{fmt.Printf("第%d个字段的值是:%v\n",i,val.Field(i)) //获取第i个字段的值}//通过reflect.Value类型操作结构体内部的方法:n2 := val.NumMethod() // 获取结构体方法的数量fmt.Println(n2)//调用方法//调用方法,方法的首字母必须大写才能有对应的反射的访问权限//方法的顺序按照ASCII码表的顺序进行排序的,对应索引从0开始,依次类推val.Method(0).Call(nil) //调用第0个方法var params []reflect.Valueparams = append(params,reflect.ValueOf(11))params = append(params,reflect.ValueOf(19))result := val.Method(1).Call(params)fmt.Println(result[0].Int()) //30
}//通过反射改变结构体的值
func TestStudentReflect2(a interface{}){//a转成reflect.Valueval := reflect.ValueOf(a)n := val.Elem().NumField() // 获取结构体字段的数量fmt.Println(n)//直接修改字段的值val.Elem().Field(0).SetString("李四")val.Elem().Field(1).SetInt(21)//调用上面定义的方法--Cset()var params []reflect.Valueparams = append(params,reflect.ValueOf("王五"))params = append(params,reflect.ValueOf(22))val.Method(2).Call(params) //CSet方法
}func main(){a := Student{Name: "张三",Age: 20,}TestStudentReflect(a)fmt.Println("")TestStudentReflect2(&a)fmt.Println(a) //{王五 22}
}

相关文章:

Golang--反射

1、概念 反射可以做什么? 反射可以在运行时动态获取变量的各种信息&#xff0c;比如变量的类型&#xff0c;类别等信息如果是结构体变量&#xff0c;还可以获取到结构体本身的信息(包括结构体的字段、方法)通过反射&#xff0c;可以修改变量的值&#xff0c;可以调用关联的方法…...

ABAP:SET CURSOR FIELD设置鼠标焦点

SET CURSOR FIELD <字段名>&#xff1a;设置鼠标焦点到该字段 SET CURSOR 设置到鼠标焦点列还是行 SET CURSOR LINE 设置鼠标焦点到行 GET CURSOR field <字段名> &#xff1a;这个相对应的获取鼠标焦点得到的字段...

【专题】2024年全球生物医药交易报告汇总PDF洞察(附原数据表)

原文链接&#xff1a;https://tecdat.cn/?p38191 在当今复杂多变的全球经济环境下&#xff0c;医药行业正面临着诸多挑战与机遇。2024 年&#xff0c;医药行业的发展态势备受关注。 一方面&#xff0c;全球生物医药交易活跃&#xff0c;2021 - 2023 年的交易中&#xff0c;已…...

LabVIEW气体检测系统

随着工业化进程的加速&#xff0c;环境污染问题愈加严峻&#xff0c;尤其是有害气体的排放对人类生存环境构成了严重威胁。为了更好地监测这些有害气体&#xff0c;开发一个高效、准确且易于操作的气体检测系统显得尤为重要。LabVIEW软件开发的气体检测系统&#xff0c;采用激光…...

LeetCode78. 子集(2024秋季每日一题 58)

给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的 子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[],[1],[2],[1,2],[3…...

推荐一款功能强大的视频修复软件:Apeaksoft Video Fixer

Apeaksoft Video Fixer是一款功能强大的视频修复软件&#xff0c;专门用于修复损坏、不可播放、卡顿、画面失真、黑屏等视频问题。只需提供一个准确且有效的样本视频作为参考&#xff0c;该软件就能将受损视频修复到与样本视频相同的质量。该软件目前支持MP4、MOV、3GP等格式的…...

Golang--网络编程

1、概念 网络编程&#xff1a;把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大、功能强的网络系统&#xff0c;从而使众多的计算机可以方便地互相传递信息、共享数据、软件、数据信息等资源。 客户端&#xff08;Client&#xff09; 客户端是请求服务…...

区块链技术在数字版权管理中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 区块链技术在数字版权管理中的应用 区块链技术在数字版权管理中的应用 区块链技术在数字版权管理中的应用 引言 区块链技术概述 …...

WPS单元格重复值提示设置

选中要检查的所有的单元格 设置提示效果 当出现单元格值重复时&#xff0c;重复的单元格就会自动变化 要修改或删除&#xff0c;点击...

Scala 的包及其导入

Scala使用包来创建用于模块化程序的命名空间。通过在Scala文件的顶部声明一个或多个包名称可以创建包&#xff0c;另一种声明包的方式是使用0&#xff0c;这种方式可以嵌套包&#xff0c;并且提供更好的范围与封装控制。对于包的导入&#xff0c;Scala与Java的区别之一便是&…...

架构师备考-概念背诵(软件工程)

软件工程 软件开发生命周期: 软件定义时期:包括可行性研究和详细需求分析过程,任务是确定软件开发工程必须完成的总目标,具体可分成问题定义、可行性研究、需求分析等。软件开发时期:就是软件的设计与实现,可分成概要设计、详细设计、编码、测试等。软件运行和维护:就是…...

DIP switch是什么?

**‌DIP开关&#xff08;DIP switch&#xff09;‌&#xff0c;也称为指拨开关&#xff0c;是一种可以人工调整的开关&#xff0c;通常以标准双列直插封装&#xff08;DIP&#xff09;的形式出现。**DIP开关一般设计在印刷电路板上&#xff0c;配合其他电子元件使用&#xff0c…...

【销帮帮-注册_登录安全分析报告-试用页面存在安全隐患】

联通支付注册/登录安全分析报告 前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨…...

2024年下半年系统分析师论文

2024年下半年11月份系统分析师考试论文 1、静态测试工具和方法 可以从代码桌前检查&#xff0c;代码审查&#xff0c;代码走查组织文章 2、DevOps开发 可以从开发&#xff0c;运维&#xff0c;测试的自动化协作入手&#xff0c;跨部门沟通需求也算 3、业务流程分析 从BPR…...

【计算机网络】万字详解 UDP 和 TCP

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. UDP1.1 UDP 报文格式1.1.1 源端口/目的端口1.1.2 报文长度1.1.3 校验和 2. TCP2.1 TCP 报文结构2.2 TCP 特…...

创建者模式之【建造者模式】

建造者模式 概述 将一个复杂对象的构建与表示分离&#xff0c;使得同样的构建过程可以创建不同的表示。 分离了部件的构造(由Builder来负责)和装配(由Director负责)。 从而可以构造出复杂的对象。这个模式适用于&#xff1a;某个对象的构建过程复杂的情况。由于实现了构建和…...

电商系统中,如何解决部分商品在短时间大量访问的单一热点问题?------Range范围分片

在电商系统中&#xff0c;部分商品在短时间内遭受大量访问的单一热点问题&#xff0c;可能引发服务器压力增大、响应速度变慢、甚至系统崩溃等问题。为了解决这一问题&#xff0c;可以采取以下策略&#xff1a; 一、增加服务器容量和带宽 提升硬件性能&#xff1a;为了应对高…...

利用VMware workstation pro 17安装 Centos7虚拟机以及修改网卡名称

通过百度网盘分享的文件&#xff1a;安装虚拟机必备软件 链接&#xff1a;https://pan.baidu.com/s/1rbYhDh8x1hTzlSNihm49EA?pwdomxy 提取码&#xff1a;omxy 123网盘 https://www.123865.com/s/eXPrVv-UsKch 提取码:eNcy 先自行安装好VMware workstation pro 17 设置虚拟机…...

前端 性能优化 (图片与样式篇)

文章目录 前端能够做哪些图片优化?1、减小图片体积2、图片缓存服务工作线程 (Service Workers)缓存IndexDB缓存图片LocalStorage缓存 3、图片懒加载使用 loading"lazy" 属性 4、不同分辨率下使用不同的图片5、使用webp格式的图片6、配置图片CDN7、减少图片和动图的使…...

A021基于Spring Boot的自习室管理和预约系统设计与实现

&#x1f64a;作者简介&#xff1a;在校研究生&#xff0c;拥有计算机专业的研究生开发团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339; 赠送计算机毕业设计600…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向

在人工智能技术呈指数级发展的当下&#xff0c;大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性&#xff0c;吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型&#xff0c;成为释放其巨大潜力的关键所在&…...

Unity中的transform.up

2025年6月8日&#xff0c;周日下午 在Unity中&#xff0c;transform.up是Transform组件的一个属性&#xff0c;表示游戏对象在世界空间中的“上”方向&#xff08;Y轴正方向&#xff09;&#xff0c;且会随对象旋转动态变化。以下是关键点解析&#xff1a; 基本定义 transfor…...

大数据治理的常见方式

大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法&#xff0c;以下是几种常见的治理方式&#xff1a; 1. 数据质量管理 核心方法&#xff1a; 数据校验&#xff1a;建立数据校验规则&#xff08;格式、范围、一致性等&#xff09;数据清洗&…...

OpenHarmony标准系统-HDF框架之I2C驱动开发

文章目录 引言I2C基础知识概念和特性协议&#xff0c;四种信号组合 I2C调试手段硬件软件 HDF框架下的I2C设备驱动案例描述驱动Dispatch驱动读写 总结 引言 I2C基础知识 概念和特性 集成电路总线&#xff0c;由串网12C(1C、12C、Inter-Integrated Circuit BUS)行数据线SDA和串…...

信息收集:从图像元数据(隐藏信息收集)到用户身份的揭秘 --- 7000

目录 &#x1f310; 访问Web服务 &#x1f4bb; 分析源代码 ⬇️ 下载图片并保留元数据 &#x1f50d; 提取元数据&#xff08;重点&#xff09; &#x1f464; 生成用户名列表 &#x1f6e0;️ 技术原理 图片元数据&#xff08;EXIF 数据&#xff09; Username-Anarch…...