GO语言学习笔记-反射篇 Study for Go ! Chapter nine - Reflect
持续更新 Go 语言学习进度中 ......
- GO语言学习笔记-类型篇 Study for Go! Chapter one - Type - slowlydance2me - 博客园 (cnblogs.com)
- GO语言学习笔记-表达式篇 Study for Go ! Chapter two - Expression - slowlydance2me - 博客园 (cnblogs.com)
- GO语言学习笔记-函数篇 Study for Go ! Chapter three - Function - slowlydance2me - 博客园 (cnblogs.com)
Study for Go ! Chapter nine - Reflect
1. TYPE
反射让我们能在运行初期探知对象的类型信息和内存结构,这从一定程度上弥补了静态语言在动态行为上的不足。同时,反射还是实现元编程的重要手段
和 C 数据结构一样,golang 对象 头部并没有类型指针,通过其自身是无法在运行期间获知任何类型的相关信息的。反射操作所需的全部信息都源自接口变量。接口变量除存储自身类型外,还会保存实际对象的类型数据
在面对类型时,需要区分 TYPE 和 KIND ,前者表示真是类型(静态类型),后者表示其基础机构(底层类型)类别
除了通过实际对象获取类型外,也可直接构造一些基础符合类型
传入对象应区分基类型和指针类型,因为它们并不属于同一类型
方法 Elem 返回指针、数组、切片、字典 (值)或通道的基类型
只有在获取结构体指针的基类型之后,才能遍历它的字段
对于匿名字段,可用多级索引 (按定义顺序)直接访问
FieldByName 不支持多级名称,如有同名遮蔽,须通过匿名字段二次获取
同样地,输出方法集时,一样区分基类型和指针类型
有一点和想象的不同,反射能探知当前包或外包的非导出结构成员 (相对 reflect 而言,当前包和外包都是 “ 外包 ”)
可用反射提取 struct tag,还能自动分解。其常用于 ORM 映射,或数据格式验证
辅助判断方法 Implements、Convertible、AssignableTo 都是运行期进行动态调用和赋值所必须的。
2. Value
和 TYPE 获取类型信息不同,Value 专注于对象实例数据读写
接口变量会复制对象,且是 Unaddressable 的,所以想要修改目标对象,就必须要使用指针
但是就算传入指针,一样需要通过 Elem 获取目标对象。因为被接口存储的指针本身是不能寻址和进行设置操作的
Attention:
不能对非导出字段直接进行设置操作,无论是当前包还是外包
Value.Pointer 和 Value.Int 等方法类似,将 Value.data 存储的数据转换为指针,目标必须是指针类型。而 UnsafeAddr 返回任何 CanAddr Value.data 地址 (相当于 & 取地址操作),比如 Elem 后的 Value,以及字段成员地址
以结构体里的指针类型字段为例,Pointer 返回该字段所保存的地址,而 UnsafeAddr 返回该字段自身的地址 (结构对象地址 + 偏移量)
可通过 Interface 方法进行类型推断和转换
也可以直接使用 Value.Int、Bool 等方法进行类型转换,但失败时会引发 Panic,且不支持 ok-idom
接口有两种 nil 状态,这是一个潜在的麻烦。解决的办法是用 IsNil 判断值是否为 nil
也可用 unsafe 转换后直接判断 iface.data 是否为零值
让人无奈的是,Value 里的某些方法 并未实现 ok-idom 或返回 error,所以得自行判断返回的是否为 Zero Value
3. Method
动态调用方法,谈不上有多麻烦,只需要按 In 列表准备好 所需参数即可
对于变参来说,用 CallSlice 要更方便一些
无法调用非导出方法,甚至无法获取有效地址
4. 构建
反射库提供了内置函数 make 和 new 的对应操作,其中最有意思的就是 MakeFunc。可以用它实现通用模板,适应不同类型数据
golang 暂不支持泛型,所以会麻烦一点
5.性能
反射在带来“ 方便 ” 的同时,也造成了很大的困扰,很多人对反射避之不及,因为它会造成很大的性能损失。
如果对性能要求较高,那么须谨慎使用反射
GO语言学习笔记-反射篇 Study for Go ! Chapter nine - Reflect的更多相关文章
- C语言学习笔记——特别篇(VScode安装使用)
B站有同步教学视频 参考博文: https://www.cnblogs.com/czlhxm/p/11794743.html 注意事项: 请在英文目录下运行!!! VScode下载链接: https: ...
- 大一C语言学习笔记(5)---函数篇-定义函数需要了解注意的地方;定义函数的易错点;详细说明函数的每个组合部分的功能及注意事项
博主学习C语言是通过B站上的<郝斌C语言自学教程>,对于C语言初学者来说,我认为郝斌真的是在全网C语言学习课程中讲的最全面,到位的一个,这个不是真不是博主我吹他哈,大家可以去B站去看看,C ...
- PHP学习笔记 - 进阶篇(7)
PHP学习笔记 - 进阶篇(7) 文件操作 读取文件内容 PHP具有丰富的文件操作函数,最简单的读取文件的函数为file_get_contents,可以将整个文件全部读取到一个字符串中. $conte ...
- PHP学习笔记 - 进阶篇(2)
PHP学习笔记 - 进阶篇(2) 函数 1.自定义函数 PHP内置了超过1000个函数,因此函数使得PHP成为一门非常强大的语言.大多数时候我们使用系统的内置函数就可以满足需求,但是自定义函数通过将一 ...
- PHP学习笔记 - 入门篇(5)
PHP学习笔记 - 入门篇(5) 语言结构语句 顺序结构 eg: <?php $shoesPrice = 49; //鞋子单价 $shoesNum = 1; //鞋子数量 $shoesMoney ...
- PHP学习笔记--入门篇
PHP学习笔记--入门篇 一.Echo语句 1.格式 echo是PHP中的输出语句,可以把字符串输出(字符串用双引号括起来) 如下代码 <?php echo "Hello world! ...
- Java学习之反射篇
Java学习之反射篇 0x00 前言 今天简单来记录一下,反射与注解的一些东西,反射这个机制对于后面的java反序列化漏洞研究和代码审计也是比较重要. 0x01 反射机制概述 Java反射是Java非 ...
- HTML语言学习笔记(会更新)
# HTML语言学习笔记(会更新) 一个html文件是由一系列的元素和标签组成的. 标签: 1.<html></html> 表示该文件为超文本标记语言(HTML)编写的.成对出 ...
- PHP学习笔记 - 进阶篇(11)
PHP学习笔记 - 进阶篇(11) 数据库操作 PHP支持哪些数据库 PHP通过安装相应的扩展来实现数据库操作,现代应用程序的设计离不开数据库的应用,当前主流的数据库有MsSQL,MySQL,Syba ...
- PHP学习笔记 - 进阶篇(10)
PHP学习笔记 - 进阶篇(10) 异常处理 抛出一个异常 从PHP5开始,PHP支持异常处理,异常处理是面向对象一个重要特性,PHP代码中的异常通过throw抛出,异常抛出之后,后面的代码将不会再被 ...
随机推荐
- 微信小程序云开发,快速生成短信验证码
使用微信小程序云函数实现注册短信验证码的管理,并不是一件分分钟的事,目前想要存储验证码只能放到数据库中,因为存储后才能和用户提交上来的验证码做比较. 管理验证码主要涉及到:生成.存储.校验.有效期管理 ...
- 给定两个字符串,均只包含英文字母,需区分大小写,一个是源字符串SS(长度<1000), 另一个是目标字符串TS(长度<1000),请问能否通过删除SS中的字符(不改变顺序)将它变换成TS,如果可以输出“YES",不可以则输出“NO"。 输入说明:第一行为源字符串SS,第二行为目标字符串TS。
import java.util.Scanner;/* 给定两个字符串,均只包含英文字母,需区分大小写,一个是源字符串SS(长度<1000), 另一个是目标字符串TS(长度<1 ...
- postman收藏 -大佬玩法。
请求顺序: https://www.cnblogs.com/superhin/p/11454832.html 在Postman脚本中发送请求(pm.sendRequest) : https:// ...
- bzoj 3561
题意:求$\sum_{i=1}^{n}\sum_{j=1}^{n}lcm(i,j)^{gcd(i,j)}$ 神仙题... 首先可能会想到一个转化,就是$lcm(i,j)=\frac{ij}{gcd(i ...
- 为动态二级域名申请https的免费证书.
前面已经讲过将nginx部署,并注册了免费的二级域名.但将网址发给儿子,儿子说微信已经不能打开http的网址了,所以一想还是研究一下https的证书申请. 网上有很多讲通过,acme的脚本来自动化申请 ...
- 1903021126 申文骏 Java 第六周作业 类与对象
项目 内容 课程班级博客链接 19级信计班(本) 作业要求链接 第六周作业 博客名称 1903021126 申文骏 Java 第六周作业 类与对象 要求 每道题要有题目,代码(使用插入代码,不会 ...
- 笔记:vue.nextTick()方法的使用详解
vue.nextTick定义: 在下次DOM更新循环结束之后执行延迟回调.在修改数据之后立即使用这个方法,获取更新后的DOM. 简单理解:数据更新了,在dom渲染后立即执行该函数 举例 注意:Vue实 ...
- 编译configure常用参数详解
./configure常用参数解释: 具体通过–help来查看具体支持什么功能.有时候编译不通过,可能依赖一些库,如果这些库关联的功能我们不需要,可以通过---disable-*lib来取消相关库的编 ...
- Arthas 查询服务器内存数据
1.打开Arthas所在位置 eg:/home 2.java -jar arthas-boot.jar 运行jar包 3.选择要执行的java jar包 eg : 1 4.执行查看命令vmtool - ...
- Vue3引用全局js
在vue3中引入全局js: 1,创建一个js文件: 2,在main.js中引入该js文件: import comm from './utils/comm' app.config.globalPrope ...