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

Go 反射

文章目录

    • 获取类型和值
    • 获取属性的类型和值
    • 通过反射修改值
    • 获取方法的名称和类型
    • 调用方法
    • 反射的缺点

获取类型和值

  • 之前讲过接口nil不一定等于空接口,因为一个 interface 底层 由 type + value 构成,只有 typevalue 都匹配,才能 ==
  • reflect.VlaueOf 就是用来获取具体的 reflect.Value
  • reflect.TypeOf 用来获取具体的 reflect.Type
func main() {var (a *Ab interface{})fmt.Println(a)if b == nil {fmt.Println("b is nil")}fmt.Println(reflect.TypeOf(b), reflect.ValueOf(b))fmt.Println(reflect.TypeOf(a), reflect.ValueOf(a))b = aif b == nil {fmt.Println("b is nil")} else {fmt.Printf("current b is %v \n", b)fmt.Println("b not eq nil")}fmt.Println(reflect.TypeOf(b), reflect.ValueOf(b))
}

image.png
上面的代码说明了,刚开始的空接口 == nil,后来的接口为啥不等于 nil,因为 type变了,虽然value 还是 nil

获取属性的类型和值

  • 通过 reflect.Value 或者 reflect.TypeNumField 获取属性数量
  • 通过 reflect.TypeField 方法 获取属性相关信息
  • 通过 reflect.ValueField 方法 获取值相关信息
package mainimport ("fmt""reflect"
)type A struct {Name stringAge  int
}func main() {var a AgetType := reflect.TypeOf(a)getValue := reflect.ValueOf(a)fmt.Println("field num", getType.NumField())for i := 0; i < getType.NumField(); i++ {field := getType.Field(i)value := getValue.Field(i)fmt.Println("field name is", field.Name, "field value is", value.Interface())}
}

image.png

通过反射修改值

  • 通过获取value的反射对象即可,reflect.ValueOf 传入的必须是指针类型,只有原始反射对象可以进行修改,可以通过 reflect.ValueElem 方法取得
  • 通过 reflect.ValueCanset 方法来判断是否可以设置
  • 通过 Set... 系列方法来设置具体类型的值
package mainimport ("fmt""reflect"
)type A struct {Name stringAge  int
}func main() {a := A{Name: "old name",}valueOfA := reflect.ValueOf(&a).Elem()nameField := valueOfA.Field(0)if nameField.CanSet() {nameField.SetString("new name")} else {fmt.Println("don't set")}fmt.Println("new value", a.Name)
}
  • 因为调用 set... 设置值,需要知道类型,可以通过 reflect.Typekind 方法获取原始类型
    • 再通过 switch 去匹配类型来调用具体的 set... 方法
package mainimport ("fmt""reflect"
)type A struct {Name stringAge  int
}func main() {a := A{Name: "old name",}fmt.Println("old value", a.Name)valueOfA := reflect.ValueOf(&a).Elem()getType := reflect.TypeOf(a)field := getType.Field(0)nameField := valueOfA.Field(0)if nameField.CanSet() {switch field.Type.Kind() {case reflect.String:fmt.Println("string")nameField.SetString("new value")}} else {fmt.Println("don't set")}fmt.Println("new value", a.Name)
}

image.png

获取方法的名称和类型

  • 先通过 reflect.TypeNumMethod 方法获取方法数量
  • 在通过 reflect.TypeMethod 方法获取到具体的方法信息 reflect.Method
package mainimport ("fmt""reflect"
)type A struct {Name stringAge  int
}func (receiver *A) SetName(name string) {receiver.Name = name
}func (receiver *A) SetAge(age int) {receiver.Age = age
}func main() {var a A//有方法是依赖指针的所以需要传指针getType := reflect.TypeOf(&a)num := getType.NumMethod()for i := 0; i < num; i++ {method := getType.Method(i)fmt.Println("method name:", method.Name, "method type:", method.Type)}
}

image.png

调用方法

  • 通过 reflect.MethodCall 方法即可调用反射对象的方法
    • Call 中 接收的参数为 reflect.Value 的切片
    • 如果反射对象的方法不需要参数,传一个 reflect.Value 的空切片即可
    • 如果反射对象需参数,那么需要由反射对像参数的 reflect.Value 组成切片,传入 Call 完成调用
package mainimport ("fmt""reflect"
)type A struct {Name stringAge  int
}type Body struct {Like stringDesc string
}func (a A) Pr() {fmt.Println("A pr")
}func (a A) Talk(b Body) {fmt.Printf("Like:%s,Desc:%s", b.Like, b.Desc)
}func main() {var a AgetType := reflect.ValueOf(a)pr := getType.Method(0)//不需要参数pr.Call([]reflect.Value{})b := Body{Like: "i'm like",Desc: "i'm desc",}talk := getType.Method(1)//Talk 需要传入 Body struct, 所以反射调用,需要传入 由 Body的 reflect.Value 组成切片参数talk.Call([]reflect.Value{reflect.ValueOf(b),})
}

image.png

反射的缺点

  • 反射慢
    • 不管什么编程语言,反射都慢
    • 反射实现里有对 reflect.kind 大量的枚举 + 类型转换 等操作
    • reflect.Value 不能复用,每次都是返回一个新的值,其中 typ 还是指针类型,涉及对指针的频繁分配,GC

image.png
image.png
image.png

相关文章:

Go 反射

文章目录 获取类型和值获取属性的类型和值通过反射修改值获取方法的名称和类型调用方法反射的缺点 获取类型和值 之前讲过接口nil不一定等于空接口&#xff0c;因为一个 interface 底层 由 type value 构成&#xff0c;只有 type 和 value 都匹配&#xff0c;才能 reflect.Vl…...

竞赛选题 深度学习卷积神经网络垃圾分类系统 - 深度学习 神经网络 图像识别 垃圾分类 算法 小程序

文章目录 0 简介1 背景意义2 数据集3 数据探索4 数据增广(数据集补充)5 垃圾图像分类5.1 迁移学习5.1.1 什么是迁移学习&#xff1f;5.1.2 为什么要迁移学习&#xff1f; 5.2 模型选择5.3 训练环境5.3.1 硬件配置5.3.2 软件配置 5.4 训练过程5.5 模型分类效果(PC端) 6 构建垃圾…...

ts-node模块

ts-node模块 是一个非官方的npm模块&#xff0c;可以直接运行JS代码。 安装&#xff1a; npm install -g ts-node使用&#xff1a; ts-node script.ts如果不安装ts-node&#xff0c;可以通过npx在线调用ts-node&#xff0c;运行ts脚本。 npx ts-node script.ts...

【VUE】ElementPlus之动态主题色调切换(Vue3 + Element Plus+Scss + Pinia)

前言 关于ElementPlus的基础主题色自定义可以参阅《【VUE】ElementPlus之自定义主题样式和命名空间》 有了上面基础的了解&#xff0c;我们知道ElementPlus的主题色调是基于CSS3变量特性进行全局控制的&#xff0c; 那么接下来我们也基于CSS3变量来实现主题色调的动态切换效果&…...

MySQL数据库基本操作1

文章目录 主要内容一.DDL1.创建表代码如下&#xff08;示例&#xff09;: 2.创建表的类型3.其他操作4.修改表结构格式代码如下&#xff08;示例&#xff09;: 二.DML1.数据插入代码如下&#xff08;示例&#xff09;: 2.数据修改代码如下&#xff08;示例&#xff09;: 3.数据删…...

Webpack简介及打包演示

Webpack 是一个静态模块打包工具&#xff0c;从入口构建依赖图&#xff0c;打包有关的模块&#xff0c;最后用于展示你的内容 静态模块&#xff1a;编写代码过程中的&#xff0c;html&#xff0c;css&#xff0c; js&#xff0c;图片等固定内容的文件 打包过程&#xff0c;注…...

面向对象设计模式——命令模式

命令设计模式(Command Pattern)是一种行为型设计模式,它的主要目的是将请求或操作封装成一个对象,从而允许参数化客户端对象,队列请求,将请求记录到日志,以及支持可撤销的操作。命令模式将请求的发出者(调用者)与请求的接收者(执行者)解耦,这使得系统更加灵活、可扩…...

selenium测试框架快速搭建(ui自动化测试)

一、介绍 selenium目前主流的web自动化测试框架&#xff1b;支持多种编程语言Java、pythan、go、js等&#xff1b;selenium 提供一系列的api 供我们使用&#xff0c;因此在web测试时我们要点页面中的某一个按钮&#xff0c;那么我们只需要获取页面&#xff0c;然后根据id或者n…...

TypeScript中的类型映射

类型映射 1. 简介 映射就是将一种类型按照映射规则&#xff0c;转成另一种类型&#xff0c;通常用于对象类型。 这里类型B通过A采用属性名索引的写法&#xff0c;完成了类型B的定义 type A {foo: number;bar: number; };type B {[prop in keyof A]: string; };这里复制了一…...

系统平台同一网络下不同设备及进程数据通讯--DDS数据分发服务中间件

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言(1)中间件的介绍(2)DDS介绍(3)发布者(4)订阅者(5)idl文件(定义msg结构体)(6)QoS(Quality of Service)策略(7)DDS测试工具介绍(…...

golang小技巧

1/有时需要把json内容返回给前段进行文本编辑json字段&#xff0c;那么最好是能返回格式化后的json&#xff0c;这样对于用户编辑页方便。这时候可以利用json.MarshalIndent(data, "", "\t")来进行格式化&#xff0c;带有缩进的marshal。 2/对holders的填…...

JavaWeb——IDEA操作:Project最终新建module

在project中创建新的module&#xff1a; 创建一个新的module很容易&#xff0c;但是它可能连接不上Tomcat&#xff0c;因此需要修改一些配置&#xff1a; 将以下地址修改为新module的地址...

前端开发技术栈(工具篇):2023深入了解webpack的安装和使用以及核心概念和启动流程(详细) 63.3k stars

目录 Webpack简介 Entry Module Chunk Loader Plugin Output Webpack的启动流程 Webpack的优缺点 Webpack的使用 1. 安装Webpack 2. 创建Webpack配置文件 3. 编写代码 4. 运行Webpack 5. 在HTML中引入打包后的文件 6. 执行编译命令 Webpack其他功能介绍 1. 使…...

[SQL开发笔记]LIKE操作符:在 WHERE 子句中搜索列中的指定模式

一、功能描述&#xff1a; LIKE操作符&#xff1a;用于在 WHERE 子句中搜索列中的指定模式。 二、LIKE操作符语法详解&#xff1a; LIKE 语法 SELECT column1, column2,…FROM table_nameWHERE column LIKE pattern; 参数说明&#xff1a; &#xff08;1&#xff09;colum…...

flutter深研

https://www.douyin.com/video/7020336319058627853 关闭系统风扇 在 Windows 操作系统上安装和配置 Flutter 开发环境 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter...

TypeScript中的declare关键字

declare关键字 1. 简介 declare关键字用来告诉编译器&#xff0c;某个类型是存在的&#xff0c;可以在当前文件中使用。 作用&#xff1a;就是让当前文件可以使用其他文件声明的类型。比如&#xff0c;自己的脚本使用外部库定义的函数&#xff0c;编译器会因为不知道外部函数…...

玫瑰红葡萄酒的基本知识

在过去的几年里&#xff0c;玫瑰红葡萄酒越来越受欢迎&#xff0c;但是如果你是饮用玫瑰红葡萄酒的新手&#xff0c;你可能想知道它是如何从其他红葡萄酒或白葡萄酒中脱颖而出的。 玫瑰红具有标志性的粉色&#xff0c;很难归类&#xff0c;那它是更适合放在红酒类还是属于白酒…...

HTTP 协议参考文档

开发者Web协议文档&#xff1a; https://developer.mozilla.org/zh-CN/docs/Web 其中子节点包含 HTTP 协议内容&#xff1a; https://developer.mozilla.org/zh-CN/docs/Web/HTTP 其内容是基于 markdown 编写的&#xff0c;对应源文件在 Github 中&#xff0c;如下&#xf…...

Python遍历删除列表元素的一个奇怪bug

假定有一个Python列表&#xff0c;比如[CFFEX.IF, CFFEX.TS,SHFE.FU]&#xff0c;现在需要将其中带‘CFFEX’前缀的所有元素都删除。在使用列表推导式一行代码搞定之前&#xff0c;用了一种最朴素的遍历删除方法&#xff0c;结果出现了意想不到的的问题。复盘了下&#xff0c;结…...

Elasticsearch部署中的两大常见问题及其解决方案

随着大数据和实时搜索的日益普及&#xff0c;Elasticsearch已经成为现代应用中不可或缺的工具。但是&#xff0c;像所有软件一样&#xff0c;部署和配置Elasticsearch可能会遇到一些问题。本文将探讨两个我最近遇到的常见问题及其解决方案。 问题描述 1. 主机名解析问题 在启…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站&#xff0c;会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后&#xff0c;网站没有变化的情况。 不熟悉siteground主机的新手&#xff0c;遇到这个问题&#xff0c;就很抓狂&#xff0c;明明是哪都没操作错误&#x…...

Chapter03-Authentication vulnerabilities

文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...