go reflect 反射

目录

一、反射

1、reflect.Type 和 reflect.Value

2、rtype 和 rvalue

3、reflect.TypeOf 工作原理

4、reflect.ValueOf 工作原理

5、reflect.ValueOf 与 reflect.TypeOf 比较

6、性能优化建议

二、问题:

1、静态类型和动态类型

2、值类型与引用类型

(1)值类型(Value Types)

(2)非值类型(Reference Types)

3、对于需要反射的结构体,使用引用类型结构体是不是更好


一、反射

1、reflect.Typereflect.Value

Go语言的反射(reflection)是通过reflect包来实现的,它提供了一些工具用于在运行时检查类型和值。reflect 的核心功能依赖于 reflect.Typereflect.Value 两个结构。reflect.Typereflect.Value 都是封装了底层数据结构,用来访问动态类型和动态值。

  • reflect.Type:表示类型信息,用来获取静态类型的信息(如类型名、类型的大小、类型的字段等)。
  • reflect.Value:它是一个结构体,封装了一个指向实际数据的指针。通过它可以获取对象的值、修改值或调用方法

2、rtypervalue

每个 Go 类型都有一个称为 rtype 的结构体,它是类型信息的底层实现。rvalue 是指实际数据值的底层实现。Go 的运行时会通过反射把数据和类型信息组合在一起,从而允许我们在运行时动态地访问或修改数据。

(1)rtype:由 Go 编译器在编译时生成,包含类型的元数据。对于每个类型(包括结构体、数组、切片、基本类型等)都有一个对应的 rtype,它在程序运行时通过反射机制被加载到内存中,以供反射操作使用。

  • 对于静态类型(如 int、struct、slice等),Go 运行时在程序启动时就加载了类型信息。reflect.TypeOf 只是返回这些类型元数据的引用,因此在这些情况下,reflect.TypeOf 的开销相对较小。对于结构体类型,编译器会根据结构体定义生成一个 rtype,这个 rtype 包含了结构体的字段信息、字段顺序、字段类型、大小等信息。
  • 对于动态类型(接口类型interface),reflect.TypeOf 需要根据实际值的动态类型来查找类型信息,涉及到更多的运行时查找操作。

(2)rvalue:在运行时创建,当通过 reflect.ValueOf() 等反射操作获取一个值时,Go 会创建一个 rvalue。它封装了数据的实际值,并与 rtype 一起用于实现反射的功能。

  • 对于值类型(如 int、array、struct 等),rvalue 会直接封装该值。
  • 对于引用类型或指针rvalue 会封装指向实际内存中数据的指针。

3、reflect.TypeOf 工作原理

当调用 reflect.TypeOf 时,Go 会查询该类型的 rtype。每个 Go 类型都有一个称为 rtype 的结构体,rtype 会包含关于该类型的元数据信息,包括类型的大小、字段、方法等。

  • 查询类型元数据reflect.TypeOf 会访问传入对象的类型信息,通常这个信息是通过指向 rtype 结构体的指针来存储的。
  • 返回类型信息reflect.TypeOf 会根据传入的值返回一个 reflect.Type,这个 reflect.Type 本质上是对 rtype 的封装,包含了该类型的各种元数据信息。

4、reflect.ValueOf 工作原理

当调用 reflect.ValueOf 时,Go 会返回一个 reflect.Value 对象,该对象封装了传入对象的实际数据(指向底层数据的指针)以及该数据的动态类型。通过 reflect.Value,可以读取或修改对象的值。

  • 类型信息reflect.ValueOf 会通过 reflect.TypeOf 获取传入对象的类型信息,即 rtype,并将其存储在 reflect.Value 中。
  • 内存分配:对于非值类型的对象(如指针、切片、数组、interface、chan等),reflect.ValueOf 会创建一个新的 reflect.Value 实例,封装传入值的内存地址(指针)或直接复制值。
  • 复制操作:对于值类型的对象(如 int、array、struct等),reflect.ValueOf 可能会创建该值的副本。这意味着如果传入的是大对象或结构体,可能会涉及到较大的内存分配和复制操作。

5、reflect.ValueOf 与 reflect.TypeOf 比较

  • reflect.TypeOf:只返回类型信息,获取的是 reflect.Type。它仅仅是对静态类型信息的封装,因此开销相对较低,特别是当类型信息已经在程序启动时加载到内存中的时候。reflect.TypeOf 不会涉及值的拷贝或修改。

  • reflect.ValueOf:返回的是实际的值,它不仅封装了类型信息,还封装了该值的实际数据。对于值类型,可能会发生复制;对于引用类型,通常会封装指针。此外,它还要处理值的可变性、指针封装等因素,因此它的开销通常大于 reflect.TypeOf

6、性能优化建议

  • 减少不必要的反射调用:频繁调用 reflect.ValueOf 或者其他反射函数会带来额外的性能开销。尽量避免在性能关键路径中使用反射。
  • 避免对大对象进行深拷贝:对结构体或数组等较大对象进行深拷贝可能会导致性能瓶颈。如果反射需要频繁复制数据,考虑是否可以优化数据结构或减少不必要的复制。
  • 使用引用(指针)类型,避免反射时的内存复制。

二、问题:

1、静态类型和动态类型

  • 静态类型 是编译时确定的,它决定了变量所能持有的值的种类和支持的操作。
  • 动态类型 是运行时确定的,通常与接口类型相关,反映了变量当前存储的数据的类型。
  • 静态类型不能改变,一旦确定就不可改变;动态类型是可变的,尤其是在接口类型中。
  • 静态类型由编译器进行静态类型检查;动态类型在运行时通过反射或类型断言访问。
  • 通过反射或类型断言,可以在运行时获取动态类型的信息。

2、值类型与引用类型

(1)值类型(Value Types)

值类型是指存储数据本身的类型,变量直接包含其数据的副本。当我们将一个值类型变量赋值给另一个变量时,实际上是将数据的副本拷贝了一份。改变新变量的值不会影响原始变量。

常见的值类型

  • 基本类型:如 intfloatboolstring
  • 结构体类型struct
  • 数组类型array

值类型的特点

  • 直接存储数据:值类型的变量直接包含数据本身,而不是数据的引用。
  • 复制传递:当将一个值类型变量赋值给另一个变量时,数据会被复制。这意味着两个变量在内存中互不影响,它们各自拥有自己的数据副本。
  • 内存分配:值类型通常会在栈上分配内存,数据存储在变量的内存区域。
(2)非值类型(Reference Types)

非值类型是指存储数据的引用或地址的类型,变量保存的是数据的指针(引用),而不是数据本身。当我们将一个非值类型变量赋值给另一个变量时,实际上是将数据的引用(地址)传递给新变量。此时两个变量指向相同的内存位置,修改一个变量的值会影响到另一个变量。

常见的非值类型

  • 指针类型pointer
  • 切片类型slice
  • 映射类型map
  • 通道类型chan
  • 接口类型interface

非值类型的特点

  • 存储数据的引用:非值类型的变量存储的是数据的引用(指针),而不是数据本身。
  • 共享数据:当将一个非值类型变量赋值给另一个变量时,它们共享同一块内存区域。修改其中一个变量会影响到其他所有引用同一内存位置的变量。
  • 内存分配:非值类型通常会在堆上分配内存(但也有可能在栈上分配,具体取决于编译器的优化)。

3、对于需要反射的结构体,使用引用类型结构体是不是更好

        在 Go 中,对于需要反射的结构体,使用引用类型结构体(即结构体指针)通常比使用值类型结构体更优。

        减少内存开销。当传递一个结构体变量时,会发生值的复制。如果传递的是结构体指针,那么反射操作将直接作用于原始结构体,而不是副本,这避免了不必要的内存开销。

        提高灵活性。结构体指针可以直接修改原始结构体的字段,而值类型结构体的修改不会影响到原始数据。

        避免不必要的 Elem 调用。如果使用结构体的值类型(即传递结构体副本),在反射时需要使用 Elem() 来解引用结构体指针。如果使用结构体指针,则不需要。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/885835.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

萤石设备视频接入平台EasyCVR海康私有化视频平台监控硬盘和普通硬盘有何区别?

在现代安防监控领域,对于数据存储和视频处理的需求日益增长,特别是在需要长时间、高稳定性监控的环境中,选择合适的存储设备和监控系统显得尤为重要。本文将深入探讨监控硬盘与普通硬盘的区别,并详细介绍海康私有化视频平台EasyCV…

一学就废|Python基础碎片,字符串编码

Unicode 万国码 在 Python 3 中,字符串由 Unicode 表示,而不是字节。ASCII 码是定义字符数字代码的最著名的标准。数字值最初只定义 128 个字符,因此 ASCII 只包含控制代码、数字、小写字母、大写字母等。然而,我们不足以表示世界…

npm list @types/node 命令用于列出当前项目中 @types/node 包及其依赖关系

文章目录 作用示例常用选项示例命令注意事项 1、实战举例**解决方法**1. **锁定唯一的 types/node 版本**2. **清理依赖并重新安装**3. **设置 tsconfig.json 的 types**4. **验证 Promise 类型支持** **总结** npm list types/node 命令用于列出当前项目中 types/node 包及其…

Qt--命令行终端程序开发

提示:本文为学习记录,若有错误,请联系作者,谦虚受教。 文章目录 前言一、头文件二、cpp文件三、使用流程如图所示 总结 前言 Constant dropping wears the stone. 一、头文件 #ifndef TERMINALWIDGET_H #define TERMINALWIDGET_…

【Linux】常用命令(2.6万字汇总)

文章目录 Linux常用命令汇总1. 基础知识1.1. Linux系统命令行的含义1.2. 命令的组成 2. 基础知识2.1. 关闭系统2.2. 关闭重启2.3. 帮助命令(help)2.4. 命令说明书(man)2.5. 切换用户(su)2.6.历史指令 3.目录…

video2gif容器构建指南

一、介绍 1.项目概述 Video2Gif 项目旨在提供一种便捷的方式,让用户能够将视频中的精彩片段快速转换为 GIF 动画。GIF 动画因其循环播放、文件体积小等特点,在社交媒体、聊天工具中广泛应用,用于表达情感、分享趣事等。 2.核心功能 视频导…

《人工智能网络安全现状(2024)》深度解读:机遇、挑战与应对策略

在当今数字化浪潮汹涌澎湃的时代,人工智能(AI)与网络安全已然深度交融,二者相互作用所塑造的发展态势正深刻重塑着我们的信息安全格局。《人工智能网络安全现状(2024)》这份报告恰似一盏明灯,为…

JVM(二、类加载系统)

类加载器 JVM的类加载通过classLoader及其子类完成的 类加载器&#xff1a; 启动类加载器&#xff08;Bootstrap ClassLoader&#xff09;&#xff1a; 负责加载存放在 <JAVA_HOME>\lib 目录中的核心类库&#xff0c;如rt.jar、resources.jar等&#xff08;或者被 -Xboot…

九、HttpMessageConverter

文章目录 1. RequestBody2. RequestEntity3. ResponseBody4. SpringMVC处理json5. SpringMVC处理ajax6. RestController注解7. ResponseEntity 1. RequestBody 2. RequestEntity 3. ResponseBody 4. SpringMVC处理json 5. SpringMVC处理ajax 6. RestController注解 7. Response…

PaddleYOLO目标检测训练(集成SwanLab可视化全过程)

PaddleYolo 是飞桨&#xff08;PaddlePaddle&#xff09;框架下的一个目标检测库&#xff0c;主要用于图像和视频中的物体检测。PaddleYOLO包含YOLO系列模型的相关代码&#xff0c;支持YOLOv3、PP-YOLO、PP-YOLOv2、PP-YOLOE、PP-YOLOE、RT-DETR、YOLOX、YOLOv5、YOLOv6、YOLOv…

移动电源测试中最核心的测试项目有哪些?-纳米软件

移动电源在如今的生活中扮演着重要的角色&#xff0c;对其进行准确的测试至关重要。以下是移动电源测试中一些较为核心的测试项目&#xff1a; 一、容量测试 内部电池容量测试&#xff1a;通过设计大量整机及内部电池容量测试实验&#xff0c;可以准确了解移动电源的实际容量…

跟着尚硅谷学vue2—进阶版4.0—Vuex1.0

5. Vuex 1. 理解 Vuex 1. 多组件共享数据-全局事件总线实现 红线是读&#xff0c;绿线是写 2. 多组件共享数据-vuex实现 vuex 不属于任何组件 3. 求和案例-纯vue版 核心代码 1.Count.vue <template><div><h1>当前求和为&#xff1a;{{ sum }}</h1&…

ChatGPT 搜索 vs Google 搜索

原文&#xff1a;Amanda Caswell - 2024.11.01 随着 OpenAI 推出的实时搜索功能&#xff0c;ChatGPT 正在逐步成为像 Google 这样的传统搜索引擎的竞争对手。ChatGPT 以其对话式的回答方式而闻名&#xff0c;它能够在没有广告干扰的情况下提供实时的上下文信息。 我迫不及待地…

LeetCode【0017】电话号码的字母组合

本文目录 1 中文题目2 最优解法&#xff1a;迭代法2.1 方法思路2.2 Python代码2.3 复杂度分析 3 题目总结 1 中文题目 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射如下&#xff08;与电话按键相…

iOS 18.2 重磅更新:6个大动作

根据外媒报道&#xff0c;iOS 18.2迎来重磅更新&#xff0c;将带来6个大动作&#xff0c;这是一次非常实用的更新。不过要注意的是&#xff0c;其中涉及到AI的功能&#xff0c;国行iPhone 暂时还不可用&#xff0c;只能等审核通过了。 1&#xff0c;Safari下载进度 过去通过S…

《TCP/IP网络编程》学习笔记 | Chapter 9:套接字的多种可选项

《TCP/IP网络编程》学习笔记 | Chapter 9&#xff1a;套接字的多种可选项 《TCP/IP网络编程》学习笔记 | Chapter 9&#xff1a;套接字的多种可选项套接字可选项和 I/O 缓冲大小套接字多种可选项getsockopt & setsockoptSO_SNDBUF & SO_RCVBUF SO_REUSEADDR发生地址绑定…

D66【python 接口自动化学习】- python基础之数据库

day66 SQL-DQL-排序分页 学习日期&#xff1a;20241112 学习目标&#xff1a;MySQL数据库-- 135 SQL-DQL-排序分页 学习笔记&#xff1a; 结果查询 结果分页限制 总结 排序和分页限制的语法 2. 关键字总结&#xff1a;

Groovy有哪些官方文档和教程可以学习?

Groovy Language Documentation&#xff1a; 这是Groovy的官方文档&#xff0c;提供了详细的语言规范、教程和指南。您可以从这里下载JavaDoc和在线文档&#xff0c;以及获取关于如何开始使用Groovy的指导。[Groovy Language Documentation][1] Groovy官方教程&#xff1a; 官…

LeetCode 3.无重复字符的最长子串

LeetCode 3.无重复字符的最长子串 思路&#x1f9d0;&#xff1a; 使用滑动窗口哈希表&#xff0c;哈希表映射每一个字符串&#xff0c;左右指针表示当前区间&#xff0c;当出现一个字符串那么就将哈希表1&#xff0c;右指针移动&#xff0c;当哈希表对应位置大于1时&#xff0…

验证码处理在自动化测试中的应用

在进行自动化测试时&#xff0c;处理验证码是一项常见的挑战&#xff0c;特别是图形验证码。每次刷新都会生成新的验证码&#xff0c;因此我们可以采用以下两种方法来获取验证码&#xff1a; 获取验证码图片链接&#xff1a;例如 src"http://example.com/getcaptcha/123&q…