Golang反射相关知识总结

news2024/11/24 19:47:59

1. Golang反射概述

Go语言的反射(reflection)是指在运行时动态地获取类型信息和操作对象的能力。在Go语言中,每个值都是一个接口类型,这个接口类型包含了这个值的类型信息和值的数据,因此,通过反射,可以获取一个值的类型信息,调用该值的方法,或者修改该值的属性等。
Go语言中的反射机制主要通过reflect包来实现。reflect包提供了Type、Value和Kind三个类型,分别表示类型信息、值信息和值的种类。其中,Type类型可以表示任何类型的信息,包括基本类型、结构体、接口类型、函数类型等。Value类型可以表示任何值,包括基本类型、结构体、接口类型、函数类型等。Kind类型则表示值的种类,如int、float、string等。
通过reflect包,可以获取一个类型的信息,例如:

package main

import (
	"fmt"
	"reflect"
)

type MyStruct struct {
	Name string
	Age  int
}

func main() {
	t := reflect.TypeOf(MyStruct{})
	fmt.Println("Type:", t.Name())
	fmt.Println("Kind:", t.Kind())
	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		fmt.Printf("%s (%s)\n", field.Name, field.Type.Name())
	}
}

实现结果:
在这里插入图片描述
上述代码中,使用reflect.TypeOf函数获取MyStruct类型的信息,然后打印出类型名称、类型种类和字段信息。
同时,也可以通过reflect包获取一个值的信息,例如:

package main

import (
	"fmt"
	"reflect"
)

type MyStruct struct {
	Name string
	Age  int
}

func main() {
	v := MyStruct{Name: "Tom", Age: 18}
	rv := reflect.ValueOf(v)
	fmt.Println("Type:", rv.Type().Name())
	fmt.Println("Kind:", rv.Kind())
	for i := 0; i < rv.NumField(); i++ {
		field := rv.Field(i)
		fmt.Printf("%s: %v\n", field.Type().Name(), field.Interface())
	}
}

实现结果:
在这里插入图片描述
上述代码中,使用reflect.ValueOf函数获取MyStruct类型的值信息,并通过rv.Type()函数获取值的类型信息,通过rv.Kind()函数获取值的种类信息,并打印出字段名称和值。同时,还可以通过rv.FieldByName函数获取指定名称的字段信息,并通过rv.FieldByNameFunc函数获取符合条件的字段信息。
除了获取类型和值的信息之外,反射还可以动态地创建类型、创建值、调用方法和修改属性等。例如,可以使用reflect.New函数动态创建一个新的值,可以使用reflect.ValueOf函数设置一个值的属性,可以使用reflect.MethodByName函数调用一个方法,可以使用reflect.ValueOf函数修改一个值的属性等。

2. 简单的反射实现修改变量的值

下面示例中,简单演示了如何直接修改City变量的值:

package main

import (
	"fmt"
	"reflect"
)

type Address struct {
	City  string
	State string
}
type Person struct {
	Name    string
	Age     int
	Address Address
}

func main() {
	p := Person{
		Name: "Alice",
		Age:  25,
		Address: Address{
			City:  "New York",
			State: "NY",
		},
	}
	// 通过反射获取到嵌套结构体中需要修改的字段的反射值
	field := reflect.ValueOf(&p).Elem().FieldByName("Address").FieldByName("City")
	// 判断该字段是否可修改,如果不可修改,则需要使用 `Elem()` 函数获取到该字段的可修改的反射值
	if !field.CanSet() {
		field = field.Elem()
	}
	// 根据需要修改的值的类型,使用反射包中的 `SetValue()` 函数来修改该字段的值
	field.SetString("Los Angeles")
	// 输出: {Alice 30 {Los Angeles NY}}
	fmt.Println("the result is:", p)
}

输出结果:
在这里插入图片描述
然而,在实际运用中,第一种方式往往不够灵活,对于使用者而言,更多的想直接调用某个方法,通过传入需要修改的变量的路径以及修改后的值来直接实现,基于此,对第一种方式进行改进。

3. 实现传入路径修改变量的值

通过将具体操作封装为ModifyValue函数来实现,传入路径后,对路径进行拆解

package main

import (
	"fmt"
	"reflect"
	"strings"
)

type Address struct {
	City  string
	State string
}
type Person struct {
	Name    string
	Age     int
	Address Address
}

func ModifyValue(req *Person, modifyPath string, value interface{}) bool {
	// 通过反射获取 req 的值
	reqValue := reflect.ValueOf(req).Elem()
	// 根据 path 找到 req 中需要修改的字段
	substrings := strings.Split(modifyPath, ".")
	for i, substring := range substrings {
		if i == 0 {
			continue
		}
		reqValue = reqValue.FieldByName(substring)
		if !reqValue.IsValid() {
			return false
		}
	}
	// 将 value 转换成需要修改的字段的类型
	newValue := reflect.ValueOf(value).Convert(reqValue.Type())
	// 设置修改后的值
	reqValue.Set(newValue)
	return true
}

func main() {
	req := Person{
		Name: "Tom",
		Age:  12,
		Address: Address{
			City:  "New York",
			State: "NY",
		},
	}
	result := ModifyValue(&req, "req.Address.City", "Los Angeles")
	fmt.Printf("the result is:%v, req.Address.City:%v", result, req.Address.City)
}

实现结果:
在这里插入图片描述
总之,Go语言的反射机制为程序提供了一种动态地获取类型信息和操作对象的能力,但是反射的效率较低,也要谨慎使用。

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

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

相关文章

Freertos学习笔记

文章目录 Freertos移植TCB控制块中断管理 (内部异常和外部中断)同步互斥与通信消息队列:邮箱:信号量:互斥量:事件组:任务通知:Freertos移植 其核心文件为,tasks.c、timers.c、queue.c、event_groups.c、croutine.c、list.c。源码兼顾了很多平台,但是我们可以删除一些…

亚马逊攀岩安全带ASTM F1772测试办理

本政策适用于主要用于攀岩或登山活动的安全带。攀岩安全带是一种装备&#xff0c;可穿戴在攀岩者或登山者的腰部和大腿处。攀岩安全带为绳子提供了一个连接点&#xff0c;并提供一种手段&#xff0c;以便在攀登、休息、绕绳下降或跌落的过程中为攀登者身体提供支撑。本政策涵盖…

整理mongodb文档:副本集一

个人博客 整理mongodb文档:副本集一 本文讲解较为粗糙&#xff0c;对于没有后台开发经验的人员&#xff0c;建议配合官网了解下相关概念。个人博客&#xff0c;日常求关注 文章概叙 文章会先花费几分钟讲解下关于垂直缩放以及水平缩放的概念&#xff0c;以方便大家对副本集…

Qt5开发及实例V2.0-第五章Qt主窗体

Qt5开发及实例V2.0-第五章Qt主窗体 第5章 Qt 5主窗体5.1.1 基本元素5.1.2 【综合实例】&#xff1a;文本编辑器5.1.3 菜单与工具栏的实现 5.2 Qt 5文件操作功能5.2.1 新建文件5.2.2 打开文件5.2.3 打印文件 5.3 Qt 5图像坐标变换5.3.1 缩放功能5.3.2 旋转功能5.3.3 镜像功能 5.…

适用于 Linux 的 Windows 子系统获得新的“镜像”网络模式

Microsoft 发布了 Windows Subsystem for Linux (WSL) 2.0.0&#xff0c;其中包含一组新的可选实验功能&#xff0c;包括新的网络模式以及自动内存和磁盘大小清理。 首先&#xff0c;新添加的“自动内存回收”功能通过回收缓存内存来动态减少 WSL 虚拟机 (VM) 的内存占用。 此…

Git学习笔记8

Gitlab&#xff1a; Gitlab是利用Ruby on Rails 一个开源的版本管理系统&#xff0c;实现一个自托管的git项目仓库&#xff0c;可通过web界面进行访问公开或私有的项目。 Gitlab安装&#xff1a; 安装之前&#xff0c;将虚拟机的内存改成了4个G。内存如果太小&#xff0c;会有…

Zipping

Zipping 信息收集端口扫描目录扫描webbanner信息收集 漏洞利用空字节绕过---->失败sqlI-preg_match bypass反弹shell 稳定维持 提权-共享库漏洞 参考&#xff1a;https://rouvin.gitbook.io/ibreakstuff/writeups/htb-season-2/zipping#sudo-privileges-greater-than-stock-…

基于Python开发的图片批量处理器(源码+可执行程序+程序配置说明书+程序使用说明书)

一、项目简介 本项目是一套基于Python开发的图片批量处理器&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Python学习者。 包含&#xff1a;项目源码、项目文档等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;…

软考高级架构师下篇-16通信系统架构设计理论与实践

目录 1. 引言2. 通信系统网络架构3. 网络构建关键技术4. 网络构建5. 前文回顾1. 引言 此章节主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本节知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中…

SpringSecurity 权限管理的实现

文章目录 前言权限管理的实现权限校验的原理FilterSecurityInterceptorAccessDescisionManagerAffirmativeBasedConsensusBasedUnanimousBased AccessDecisionVoterWebExpressionVoterAuthenticatedVoterPreInvocationAuthorizationAdviceVoterRoleVoterRoleHierarchyVoter 前言…

HEXO 基本使用

1 新建、编辑并预览文章 1. 新建文章 hexo new [layout] title # 或 hexo n [layout] title创建文章前要先选定模板&#xff0c;在hexo中也叫做布局。hexo支持三种布局&#xff08;layout&#xff09;&#xff1a;post(默认)、draft、page。我们先介绍如何使用已有布局…

【Unity 实用工具篇】✨ | 编辑器扩展插件 Odin Inspector,进阶功能学习

前言【Unity 实用工具篇】✨ | 编辑器扩展插件 Odin,进阶功能学习一、Odin Attributes Overview 特性篇1.1 提示信息1.1.1 Title、InfoBox1.1.2 DetailedInfoBox1.2 各类限制1.2.1 限制数值范围1.2.2 限制只读1.2.3 限制属性搜索范围1.4 Required 限制必须赋值1.3 数值变化时触…

我们感知的内容是由大脑最支持的假设决定的吗?

某种意义上讲&#xff0c;我们从未直接体验到感觉信号本身&#xff0c;而是通过对这些信号的解读和处理来感知和理解外界。 感觉信号是由我们的感官系统接收到的来自外部世界的刺激所产生的物理信号。例如&#xff0c;视觉感觉信号由我们的眼睛接收光线并将其转化为神经脉冲&am…

爬虫获取一个网站内所有子页面的内容

上一篇介绍了如何爬取一个页面内的所有指定内容&#xff0c;本篇讲的是爬去这个网站下所有子页面的所有指定的内容。 可能有人会说需要的内容复制粘贴&#xff0c;或者直接f12获取需要的文件下载地址一个一个下载就行了&#xff0c;但是如下图十几个一级几十个二级一百多个疾病…

STM32-无人机-电机-定时器基础知识与PWM输出原理

电机控制基础——定时器基础知识与PWM输出原理 - 掘金单片机开发中&#xff0c;电机的控制与定时器有着密不可分的关系&#xff0c;无论是直流电机&#xff0c;步进电机还是舵机&#xff0c;都会用到定时器&#xff0c;比如最常用的有刷直流电机&#xff0c;会使用定时器产生PW…

「UG/NX」Block UI 指定方位SpecifyOrientation

✨博客主页何曾参静谧的博客📌文章专栏「UG/NX」BlockUI集合📚全部专栏「UG/NX」NX二次开发「UG/NX」BlockUI集合「VS」Visual Studio「QT」QT5程序设计「C/C+&#

怎么打开mysql题库练习系统

在正式考试的时候&#xff0c;大题上方会有一个启动的按钮&#xff0c;非常明显。 我在考试之前买了题库&#xff0c;但是一直没找到怎么进入mysql &#xff08;指的不是平时自己做项目的入口&#xff0c;是考试系统仿真&#xff09; 其实是要下载一个软件&#xff1a; 就在…

大数据与云计算实验一

检查是否开启 sudo service docker status 开启服务 sudo service docker start 运行服务 sudo docker run -itd -p 8080:80 nginx 查询ID docker ps -all 进入容器shell sudo docker exec -it <容器ID或容器名称> /bin/bash 找到/usr/share/nginx/html/index.…

【小沐学CAD】虚拟仿真开发工具:GL Studio

文章目录 1、简介2、软件功能3、应用行业3.1 航空3.2 汽车3.3 防御3.4 工业3.5 电力与能源3.6 医疗3.7 空间3.8 科技 结语 1、简介 https://disti.com/gl-studio/ https://ww2.mathworks.cn/products/connections/product_detail/gl-studio.html DiSTI 是 HMI 软件、虚拟驾驶舱…

zabbix自定义key

用户参数&#xff08;zabbix-agent&#xff09; 介绍 自定义用户参数&#xff0c;也就是自定义key&#xff0c;有时&#xff0c;你可能想要运行一个代理检查&#xff0c;而不是Zabbix的预定义&#xff0c;你可以编写一个命令来检索需要的数据&#xff0c;并将其包含在代理配置…