golang反射

news2025/1/18 9:53:03

go反射

  • 反射
    • 基本介绍
    • 应用场景
    • 基本使用
    • 结构体
    • 注意
    • 练习
    • 最佳实践
      • 遍历结构体的方法,调用接头体的方法,获取结构体的标签

反射

基本介绍

  1. 反射可以在运行时动态获取变量的各种信息,比如变量的类型(type)、类别(kind)
  2. 如果是结构体变量,可以获取到结构体本身的信息(包括结构体的字段、方法)
  3. 通过反射,可以修改变量的值,可以调用关联的方法
  4. 使用反射,需要import(“reflect”)
  5. 示意图
    在这里插入图片描述

应用场景

  1. reflect.TypeOf(变量名) 获取变量的类型,返回reflect.Type类型
  2. reflect.ValueOf(变量名)获取变量的值,返回reflect.Value 是一个结构体类型,通过reflect.Value,可以获取该变量的很多信息
  3. 变量、interface{} 和 reflect.Value 是可以相互转换的,这点在实际开发中经常会用到

基本使用


// 演示反射
func reflectTest01(b interface{}) {
	rTyp := reflect.TypeOf(b)
	fmt.Println("TypeOf", rTyp)
	fmt.Printf("TypeOf Type %T \n", rTyp)
	value := reflect.ValueOf(b)
	fmt.Println("ValueOf", value)
	fmt.Printf("ValueOf %T\n", value)

	fmt.Println(value.Int() + 13)

	// 将 rVal 转成interface{}
	iv := value.Interface()
	// 将 any 断言
	num2 := iv.(int)
	fmt.Println(num2)

}

func TestReflect(t *testing.T) {
	var num int = 100
	reflectTest01(num)
}

结构体


// 演示反射
func reflectTest01(stu Student) {
	stuType := reflect.TypeOf(stu)
	fmt.Println("stuType", stuType)
	fmt.Println("stuType Kind", stuType.Kind())
	stuValue := reflect.ValueOf(stu)
	fmt.Println("stuValue", stuValue)
	fmt.Println("stuValue Kind", stuValue.Kind())

	stuIv := stuValue.Interface()
	fmt.Printf("接口 类型 %T \n", stuIv)

	student, ok := stuIv.(Student)
	if ok {
		fmt.Printf("接口 类型 %T \n", student)
	}

}

type Student struct {
	Name string
	Age  int
}

func TestReflect(t *testing.T) {
	student := Student{
		"tom", 13,
	}
	reflectTest01(student)
}

注意

  1. reflect.Value.Kind 获取变量的类别,返回的是一个产量
  2. Type 是类型 Kind是类别,Type和Kind可能相同,可能不同
    比如:int Type :int ; Kind:int
    Student Type:Student ; Kind:struct
  3. 通过反射可以在让变量在 interface{} 和 Reflect.Value 之间相互转换
  4. 使用反射的方式来获取变量的值(并返回对应的类型),要求数据类型匹配,否则panic
  5. 通过反射修改变量,注意当使用setXxx方法来设置需要通过对应的指针来完成,同时需要使用reflect.Value.Elem
func TestReflect(t *testing.T) {
	i := 10
	iValue := reflect.ValueOf(&i)
	// 获取指针进行修改值
	iValue.Elem().SetInt(20)
	fmt.Println(i)
}

练习

func TestReflect(t *testing.T) {
	var v float64 = 1.2
	value := reflect.ValueOf(v)
	vType := value.Type()
	vKind := value.Kind()
	fmt.Println(vType, vKind, value)

	fv, ok := value.Interface().(float64)
	if ok {
		fmt.Printf("FV 的值 %v 类型 %T \n", fv, fv)
	}
}

最佳实践

遍历结构体的方法,调用接头体的方法,获取结构体的标签

func TestReflect(t *testing.T) {
	m := Monster{
		Name:  "黄书狼",
		Age:   400,
		Score: 30.8,
	}
	mType := reflect.TypeOf(m)
	mValue := reflect.ValueOf(m)

	if mValue.Kind() != reflect.Struct {
		fmt.Println("expect struct")
		return
	}
	num := mValue.NumField()
	fmt.Printf("struct has %d field \n", num)
	for i := 0; i < num; i++ {
		fmt.Printf("字段 %d 值为%v\n", i, mValue.Field(i))
		// 获取struct标签,注意需要通过reflect.Type 来获取tag标签的值
		tagVal := mType.Field(i).Tag.Get("json")
		if tagVal != "" {
			fmt.Printf("字段 %d : tag为%v\n", i, tagVal)
		}
	}
	methodNum := mValue.NumMethod()
	fmt.Printf("struct has %d method \n", methodNum)

	mValue.Method(1).Call(nil) // 按照名字的ASC码排序
	//mValue.MethodByName("Print").Call(nil)
	var params []reflect.Value
	params = append(params, reflect.ValueOf(10))
	params = append(params, reflect.ValueOf(40))
	res := mValue.Method(0).Call(params)
	fmt.Println("res ", res[0].Int())
}

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

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

相关文章

Java应用开发必备:使用 easy-captcha 组件生成验证码的详细介绍

一、前言 最近系统开发在优化验证码的相关功能&#xff0c;第一反应就是有没有开源的第三方组件可以使用呢。 在一番寻觅以后&#xff0c;还真发现一个好用的第三方验证码组件Easy-captcha。Easy-captcha是一个开源的Java库&#xff0c;用于生成和验证验证码&#xff0c;它的…

RGB灯珠的控制-单片机通用模板

RGB灯珠的控制-单片机通用模板 一、RGB控制的原理二、RGB.c的实现三、RGB.h的实现四、color色彩空间变换以及控制渐变一、RGB控制的原理 ①通过IO发送脉冲识别0/1编码,组合24Bit的RGB数据,从而控制RGB;②每个RGB灯珠通过DIN、DOU进行级联起来;③通过HSV色彩转换成RGB从而控…

Tomcat架构设计精髓分析-Connector高内聚低耦合设计

优秀的模块化设计通常都会采用高内聚、低耦合 高内聚是指相关度比较高的功能要尽可能集中&#xff0c;不要分散。低耦合是指两个相关的模块要尽可能减少依赖的部分和降低依赖的程序&#xff0c;不要让两个模块产中强依赖。 Tomca连接器需要实现的功能: 监听网络端口 接受网络…

手撕netty源码(一)- NioEventLoopGroup

文章目录 前言一、NIO 与 netty二、NioEventLoopGroup 对象的创建过程2.1 创建流程图2.2 EventExecutorChooser 的创建 前言 processOn文档跳转 本文是手撕netty源码系列的开篇文章&#xff0c;会先介绍一下netty对NIO关键代码的封装位置&#xff0c;主要介绍 NioEventLoopGro…

使用PyCharm开发工具创建工程

一. 简介 前面文章实现了开发 python程序使用的 开发工具PyCharm&#xff0c;本文来学习使用 PyCharm开发工具创建一个 python工程。 二. 使用PyCharm开发工具创建工程 1. 首先&#xff0c;打开 PyCharm开发工具&#xff0c;打开 "New project" 选项&#xff1a; …

hive启动beeline报错

问题一在zpark启动集群报错 出现上面的问题执行以下代码 chmod 777 /opt/apps/hadoop-3.2.1/logs 问题二启动beeline报错 执行 cd /opt/apps/hadoop-3.2.1 bin/hadoop dfsadmin -safemode leave 问题三执行查询语句报错 执行 set hive.exec.mode.local.autotrue;

java接口加密解密

这里写目录标题 controller加解密工具类加密&#xff08;本质是对ResponseBody加密&#xff09;解密&#xff08;本质是对RequestBody传参解密&#xff09;注解 controller Controller public class PathVariableController {GetMapping(value "/test")ResponseBod…

Redis缓存问题:穿透,击穿,雪崩等

Redis缓存问题:穿透,击穿,雪崩等 在高并发场景下,数据库往往是最薄弱的环节,我们通常选择使用redis来进行缓存,以起到缓冲作用,来降低数据库的压力,但是一旦缓存出现问题,也会导致数据库瞬间压力过大甚至崩溃,从而导致整个系统崩溃.今天就聊聊常见的redis缓存问题. 缓存击穿 …

相关分析方法

目录 1.什么是相关分析方法 2.相关系数 3.常见的相关分析方法 3.1.皮尔逊相关系数 3.2.斯皮尔曼等级相关 ​​​​​​​3.3.肯德尔等级相关 ​​​​​​​3.4.其它 4.应用 5.注意事项 6.结语 1.什么是相关分析方法 相关分析是数据分析中的一种统计方法&#xff0c…

[C++基础学习]----02-C++运算符详解

前言 C中的运算符用于执行各种数学或逻辑运算。下面是一些常见的C运算符及其详细说明&#xff1a;下面详细解释一些常见的C运算符类型&#xff0c;包括其原理和使用方法。 正文 01-运算符简介 算术运算符&#xff1a; a、加法运算符&#xff08;&#xff09;&#xff1a;对两个…

RabbitMQ(高级)笔记

一、生产者可靠性 &#xff08;1&#xff09;生产者重连&#xff08;不建议使用&#xff09; logging:pattern:dateformat: MM-dd HH:mm:ss:SSSspring:rabbitmq:virtual-host: /hamllport: 5672host: 192.168.92.136username: hmallpassword: 123listener:simple:prefetch: 1c…

AWTK 开源串口屏开发(17) - 通过 MODBUS 访问数组数据

在 AWTK 串口屏中&#xff0c;内置了 MODBUS Client Channel 的模型&#xff0c;不用编写代码即可实现在 ListView 中显示数组数据。 MODBUS 协议一次只能读取 125 个 WORD&#xff0c;AWTK-MODBUS Client Channel 支持长数据&#xff0c;自动分成多个请求访问。 1. 功能 不用…

浏览器的同源策略与解决跨域

同源策略&#xff08;协议、域名、端口&#xff09; 同源策略&#xff08;Same-Origin Policy&#xff09;是一个在浏览器安全模型中被实施的重要安全机制。它是基于域名、协议和端口号的限制&#xff0c;用于防止不同源的网页间的恶意行为和信息泄露。 根据同源策略&#xf…

【Diffusion实战】训练一个diffusion模型生成蝴蝶图像(Pytorch代码详解)

上一篇Diffusion实战是确确实实一步一步走的公式&#xff0c;这回采用一个更方便的库&#xff1a;diffusers&#xff0c;来实现Diffusion模型训练。 Diffusion实战篇&#xff1a;   【Diffusion实战】训练一个diffusion模型生成S曲线&#xff08;Pytorch代码详解&#xff09;…

【Linux学习】​​学习Linux的准备工作和Linux的基本指令

˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如…

并并并并·病查坤

P1、什么是并查集 引用自百度百科&#xff1a; 并查集&#xff0c;在一些有N个元素的集合应用问题中&#xff0c;我们通常是在开始时让每个元素构成一个单元素的集合&#xff0c;然后按一定顺序将属于同一组的元素所在的集合合并&#xff0c;其间要反复查找一个元素在哪个集合…

【数据标注】使用LabelImg标注YOLO格式的数据(案例演示)

文章目录 LabelImg介绍LabelImg安装LabelImg界面标注常用的快捷键标注前的一些设置案例演示检查YOLO标签中的标注信息是否正确参考文章 LabelImg介绍 LabelImg是目标检测数据标注工具&#xff0c;可以标注两种格式&#xff1a; VOC标签格式&#xff0c;标注的标签存储在xml文…

insightface 环境配置

首先创建续集环境&#xff1a; conda create -n insightface3 python3.8 然后打开此虚拟环境&#xff1a;conda activate insightface3 然后安装&#xff1a; pip install insightface 再安装&#xff1a;pip install onnxruntime-gpu 就可以了

零基础俄语培训哪家好,柯桥俄语培训

1、Мощный дух спасает расслабленное тело. 强大的精神可以拯救孱弱的肉体。 2、Единственное правило в жизни, по которому нужно жить — оставаться человеком в лю…