GO语言基础之reflect反射
反射reflection
1. 反射可以大大的提高程序的灵活性,使得 interface{} 有更大的发挥余地
2. 反射使用 TypeOf 和 ValueOf 函数从接口中获取目标对象信息
3. 反射会将匿名字段作为独立字段(匿名字段本质)
4. 想要利用反射修改对象状态,前提是 interface.data 是 settable,即 pointer-interface
5. 通过反射可以“动态”调用方法
示例一:
举例说明反射使用 TypeOf 和 ValueOf 来取得传入类型的属性字段于方法
package mainimport ("fmt""reflect" )//定义一个用户结构体 type User struct {Id intName stringAge int }//为接口绑定方法 func (u User) Hello() {fmt.Println("Hello World.") }//定义一个可接受任何类型的函数(空接口的使用规则) func Info(o interface{}) {t := reflect.TypeOf(o) //获取接受到到接口到类型fmt.Println("Type:", t.Name()) //打印对应类型到名称(这是reflect中自带到)//Kind()方法是得到传入类型到返回类型;下面执行判断传入类型是否为一个结构体if k := t.Kind(); k != reflect.Struct {fmt.Println("传入的类型有误,请检查!")return}v := reflect.ValueOf(o) //获取接受到到接口类型包含到内容(即其中到属性字段和方法)fmt.Println("Fields:") //如何将其中到所有字段和内容打印出来呢?/**通过接口类型.NumField 获取当前类型所有字段个数*/for i := 0; i < t.NumField(); i++ {f := t.Field(i) //取得对应索引的字段val := v.Field(i).Interface() //取得当前字段对应的内容fmt.Printf("%6s: %v = %v\n", f.Name, f.Type, val)}/**通过接口类型.NumMethod 获取当前类型所有方法的个数*/fmt.Println("Method:")for i := 0; i < t.NumMethod(); i++ {m := t.Method(i) //取得对应索引的方法fmt.Printf("%6s: %v\n", m.Name, m.Type)} }func main() {u := User{1, "OK", 12}Info(u)//Info(&u) 如果传入的是结构体的地址或指针(pointer-interface),那么在Info函数中的Kind方法进行判断时就会被拦截返回 }
运行结果如下:
1
2
3
4
5
6
7
|
Type: User
Fields:
Id: int = 1
Name: string = OK
Age: int = 12
Method:
Hello: func(main.User)
|
示例二:
如何通过反射得道结构当中匿名或者嵌入字段
package mainimport ("fmt""reflect" )//定义一个用户结构体 type User struct {Id intName stringAge int }type Manager struct {User //定义了一个匿名引用title string }func main() {m := Manager{User: User{1, "OK", 15}, title: "123"}t := reflect.TypeOf(m)//取得类型中的字段是否为匿名字段fmt.Printf("%6v\n", t.Field(0))/**打印内容:{User main.User 0 [ 0] true},其中true表示是匿名类型那么想要取匿名类型中的字段又该怎么取呢?这里需要使用序号组,传入要取的切片即可*/fmt.Printf("%v\n", t.FieldByIndex([]int{0, 0}))/**其中上面切片传入的是{0, 0},1. 第一个0表示当前结构Manager取匿名User是第一个即为02. 第二个0表示取得的结构User中要取第一个元素Id相对于User来说也是第一个即为0,如果要取Name则需传入[]int{0, 1}那么既然可以取出来内容,那么我们就可以尝试着进行修改,怎么做呢?*/tchage := reflect.ValueOf(&m) //想要修改和我们之前所说的传入值类型和指针类型是一致的,要想修改需要传入对应指针类型tchage.Elem().FieldByIndex([]int{0, 0}).SetInt(999) //传入指针需要通过 .Elem() 来取得对应的值内容,之后再想取哪个再继续使用序号组fmt.Println(tchage.Elem().FieldByName("title"))fmt.Println(tchage) }
运行结果:
1
2
3
4
|
{ User main.User 0 [ 0] true }
{Id int 0 [0] false }
123
&{{999 OK 15} 123}
|
示例三:
那么让我们来写一个比较完整的通过反射修改结构体内部字段内容
package mainimport ("fmt""reflect" )//定义一个用户结构体 type User struct {Id intName stringAge int }func main() {u := User{1, "OK", 13}fmt.Println(u)Set(&u)fmt.Println(u) }//定义一个可以接受任何类型的空接口 func Set(o interface{}) {v := reflect.ValueOf(o)//通过反射修改类型中的内容需要传入指针,为了防止传入有误故在这里进行相关过滤验证判断(这前这快是已经说过的)if v.Kind() == reflect.Ptr && !v.Elem().CanSet() {//reflect.Ptr对应为指针类型;v.Elem().CanSet()取得对应地址下的内容并查看其是否可以进行修改fmt.Println("传入的类型有误,请检查!")return} else {v = v.Elem() //将实际对象(包含详情内容)进行赋值}f := v.FieldByName("Name")f1 := v.FieldByName("Id1")if !f.IsValid() { //判断通过名称获取得到到内容是否为空值fmt.Println("没有Name对应属性字段")return}if !f1.IsValid() {fmt.Println("没有Id1对应属性字段")}if f.Kind() == reflect.String {f.SetString("HelloWorld")} }
运行结果:
1
2
3
|
{1 OK 13}
没有Id1对应属性字段
{1 HelloWorld 13}
|
示例四:
那么让我们来写一个比较完整的通过反射对方法等动态调用
package mainimport ("fmt""reflect" )//定义一个用户结构体 type User struct {Id intName stringAge int }//为User绑定方法 func (u User) HelloDisplay(name string) {fmt.Println("Hello", name, " my name is ", u.Name) }func main() {u := User{1, "OK", 29}u.HelloDisplay("jack") //正常调用/**以下方式为反射调用,最优到代码写法就是新写一个方法且在开始是通过kind判断类型是否正确且需要判断有没有对应方法等*/v := reflect.ValueOf(u) //通过反射得到类型内容methodV := v.MethodByName("HelloDisplay") //通过方法名称得道方法实体args := []reflect.Value{reflect.ValueOf("jack")} //设置反射传入的参数methodV.Call(args) }
运行结果:
1
2
|
Hello jack my name is OK
Hello jack my name is OK
|
GO语言基础之reflect反射相关推荐
- GO语言reflect反射篇
1.1 reflect反射是什么,为什么需要反射 GO 反射的意义:Go 语言的 ORM 库离不开它,Go 语言的 json 序列化库离不开它, fmt包字符串格式化离不开它,Go 语言的运行时更是离 ...
- Java 语言基础(异常机制和File类,IO流,多线程,网络编程,反射机制)
原文:Java 语言基础(异常机制和File类,IO流,多线程,网络编程,反射机制) 异常机制和File类 异常机制 基本概念 异常就是"不正常"的含义,在 Java 语言中主要指 ...
- Java基础10(反射)
Java基础10(反射) 1 什么是反射 官方解释:反射(reflection)技术通常被用来检测和改变应用程序在 Java 虚拟机中的行为表现.它是一个相对而言比较高级的技术,反射是一种强有力的技术 ...
- Java基础13:反射与注解详解
Java基础13:反射与注解详解 什么是反射? 反射(Reflection)是Java 程序开发语言的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性. Orac ...
- golang快速入门--语言基础
语言基础语法 行分隔符 在golang中,多个语句写在同一行,必须使用分号 " ; " 分隔开 注释 单行注释 使用// 即可表示 多行注释 使用/-/ 表示 字符串连接 允许使用 ...
- Go语言设计与实现 -- 反射
Go的反射有哪些应用? IDE中代码的自动补全 对象序列化 fmt函数的相关实现 ORM框架 什么情况下需要使用反射? 不能明确函数调用哪个接口,需要根据传入的参数在运行时决定. 不能明确传入函数的参 ...
- go语言基础学习笔记完整版
目录 背景 基础 helloworld 变量 常量 数据类型 基本数据类型与复杂数据类型 值类型与引用类型 查看变量类型 字符与字符串 类型转换 指针 打包 读取控制台数据 for-range遍历 生 ...
- Java基础-注解和反射
Java基础-注解和反射 前言 对于注解,我主要还是在自定义APT还有运行时反射获取类来让自己能够构建出复用性更高的代码逻辑. 知识点1-注解: 注解的应用场景由元注解@Retention来进行指定, ...
- Java基础教程:反射基础
Java基础教程:反射基础 引入反射 反射是什么 能够动态分析类能力的程序称为反射. 反射是一种很强大且复杂的机制. Class类 在程序运行期间,Java运行时系统始终为所有对象维护一个被称为运行时 ...
最新文章
- Ubuntu 14.04安装搜狗拼音linux版应该注意的问题
- ajax局部刷新后,如何让局部中的百度分享重新加载
- 大数据落地决胜的关键——百分点BASIC模型
- 我的学习之路_第二十三章_HTML
- SpringBoot快速集成kafka
- Java继承多态经典案例分享
- mysql自带的卸数工具_数据库卸数必备工具下载-数据库数据导出工具(DBexport)下载v1.3官方版-西西软件下载...
- dfa matlab用法,关于使用MF-DFA方法计算广义Hurst指数的MATLAB操作问题
- Python——常见数据类型的调试笔记(“如何通过Debug信息判断数据类型”)
- html弹出保存文件对话框_初步了解CAD的模板文件
- 重学AS3之基础知识重点记忆
- 多线程 + java nio 实现按行读取并处理超大文件
- 计算机内录,如何电脑内部录音,介绍一款可以录制电脑内部声音的工具
- 哪些Amazon erp是可以免费使用的?
- video.js在react中实现视频播放(video.js)
- 清理系统垃圾缓存BAT
- 托福高频真词List12 // 附托福TPO阅读真题
- linux脚本命令同时起多个命令行窗口
- Btree/B+tree原理及区别(详解)
- SDL编程入门(27)碰撞检测
热门文章
- mysql hive 内置函数_Hive中与时间相关的内置函数
- shell 判断_shell之条件判断和流程控制
- 按覆盖地理范围的不同计算机网络可分为,按网络覆盖的地理范围进行分类,计算机网络可以分为:...
- 公共端接正极还是负极_【动力电池大事记】现代摩比斯启动首批模组工厂,松下拟挪威建厂,200名车主起诉现代,密歇根大学开发锂金属固态电池及“无负极”工艺...
- java循环制作万年历,java使用Calendar制作万年历
- 高压放电与防静电塑料包装
- 一个简单的Apriltag,数字,动物水果分类器
- 第十六届全国大学生智能车竞赛-航天智慧物流创意组-技术培训
- 比Tiny YOLOv3小8倍,性能提升11个点,4MB的网络也能做目标检测
- TPF111视频信号放大器研究