Golang:reflect反射的使用例子
1.reflect包作用
reflect包定义了“反射”相关能力,“反射”在计算机学中是指计算机程序在运行时(runtime)可以访问、检测和修改它本身状态或行为的一种能力。基于反射特性可以通用化地解决一些需要频繁修改代码及硬编码问题,但是执行效率会被降低。
2.核心API
参考官方文档:https://pkg.go.dev/reflect#pkg-functions
3.使用案例
3.1.类型判断
- 用途:判断接口属于某种类型后进行特定处理
- 主要使用:TypeOf、Kind
type User struct {Name stringAge int
}type IUserService interface {GetUser(userID int64) User
}func reflectType() {var (intType intstringType *stringmapType map[string]interface{}structType *UserinterfaceType IUserService)var types []interface{}types = append(types, intType)types = append(types, stringType)types = append(types, mapType)types = append(types, structType)types = append(types, interfaceType)// 类型判断for i, v := range types {rtyp := reflect.TypeOf(v)if rtyp == nil {fmt.Printf("(%v)类型获取Type为nil,跳过\n", i)continue}rkind := rtyp.Kind()// 如果为指针类型,还原出真实类型if rtyp.Kind() == reflect.Ptr {fmt.Printf("(%v)指针类型: %v\n", i, rkind.String())rtyp = rtyp.Elem()}rkind = rtyp.Kind()fmt.Printf("(%v)类型%v\n", i, rkind.String())}
}
输出:
(0)类型int
(1)指针类型: ptr
(1)类型string
(2)类型map
(3)指针类型: ptr
(3)类型struct
(4)类型获取Type为nil,跳过
3.2.变量值获取
- 用于:获取类型的值
- 主要使用:ValueOf、Kind
func reflectValue() {var (intType int = 10stringType string = "hello world"mapType map[string]interface{} = nil)var types []interface{}types = append(types, intType)types = append(types, stringType)types = append(types, mapType)// 类型判断for i, v := range types {rval := reflect.ValueOf(v)if rval.Kind() == reflect.Ptr {rval = rval.Elem()}fmt.Printf("(%v)的值%v\n", i, rval.Interface())}
}
输出:
(0)的值10
(1)的值hello world
(2)的值map[]
3.3.遍历结构体的字段及值
- 用途:遍历未知类型结构体的字段及值,避免硬编码结构体处理
- 主要使用:TypeOf、ValueOf、NumField
func rangeStruct() {u := User{Name: "arong",Age: 23,Favors: []Favor{{Name: "篮球",ID: 1,},{Name: "唱跳",ID: 2,},{Name: "RAP",ID: 3,},},}rval := reflect.ValueOf(&u)if rval.Kind() == reflect.Ptr {rval = rval.Elem()}for i := 0; i < rval.NumField(); i++ {name := rval.Type().Field(i).Nameval := rval.Field(i).Interface()fmt.Printf("字段%v值为%v\n", name, val)}
}
输出:
字段Name值为arong
字段Age值为23
字段Favors值为[{篮球 1} {唱跳 2} {RAP 3}]
3.4.结构体字段赋值
- 用途:对未知结构体的特定字段进行赋值
- 主要使用:ValueOf、FieldByName、CanSet、Set
func reflectSetValue() {u := User{Name: "arong",Age: 23,}fmt.Printf("原始字段值:%#v\n", u)// 一定要取指针,不然无法赋值rval := reflect.ValueOf(&u).Elem()rvalNameField := rval.FieldByName("Name")// 字段是否可写入if rvalNameField.CanSet() {rvalNameField.Set(reflect.ValueOf("pbrong"))}fmt.Printf("改变已知字段值:%#v\n", u)
}
3.5.函数及方法调用
- 用途:使用反射动态调用指定函数及方法
- 主要使用:
type User struct {Name stringAge intFavors []Favor
}type IUserService interface {GetUser(userID int64) User
}type UserService struct {
}func (u *UserService) GetUser(userID int64) User {user := User{Name: "defaultTestUser",Age: -1,Favors: []Favor{},}fmt.Printf("GetUser exec: result = %#v\n", user)return user
}func TestFunc(names string) {fmt.Printf("TestFunc exec: result = %v\n", names)
}func reflectSetValue() {u := User{Name: "arong",Age: 23,}fmt.Printf("原始字段值:%#v\n", u)// 一定要取指针,不然无法赋值rval := reflect.ValueOf(&u).Elem()rvalNameField := rval.FieldByName("Name")// 字段是否可写入if rvalNameField.CanSet() {rvalNameField.Set(reflect.ValueOf("pbrong"))}fmt.Printf("改变已知字段值:%#v\n", u)
}
输出:
TestFunc exec: result = pbrong
GetUser exec: result = main.User{Name:"defaultTestUser", Age:-1, Favors:[]main.Favor{}}
GetUser resp: main.User{Name:"defaultTestUser", Age:-1, Favors:[]main.Favor{}}
4.避免滥用反射
反射使用不当可能会影响程序的性能和可读性。因此,在 Go 中,我们通常建议尽可能地避免滥用反射。
主要的原因是,反射的本质是一种运行时类型转换,会导致一定的开销。因为它需要动态地获取类型信息,进行类型检查,以及在运行时动态地分配内存等。这些操作都比静态类型转换需要更多的计算资源和时间。
另外,由于反射的使用不够直观和简洁,可能会降低代码的可读性和可维护性。特别是当开发人员不了解反射的工作原理时,容易出现一些难以调试和排查的问题。
因此,通常情况下我们应该尽可能地避免滥用反射。只有在必要的场景下才使用反射,例如需要在运行时动态地创建对象、调用函数、解析数据等。在其他场景下,我们应该尽可能使用 Go 的静态类型系统和语言特性,使得代码更加简洁、高效和可读。
相关文章:
Golang:reflect反射的使用例子
1.reflect包作用 reflect包定义了“反射”相关能力,“反射”在计算机学中是指计算机程序在运行时(runtime)可以访问、检测和修改它本身状态或行为的一种能力。基于反射特性可以通用化地解决一些需要频繁修改代码及硬编码问题,但是…...
markdown常用语法--花括号(超详细)
💌 所属专栏:【Markdown常用语法】 😀 作 者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! …...
BN、SyncBN、IN、LN、GN学习记录
1 BatchNormBN的原理BN是计算机视觉最常用的标准化方法,它沿着N、H、W维度对输入特征图求均值和方差,随后再利用均值和方差来归一化特征图。计算过程如下图所示,1)沿着通道维度计算其他维度的均值;2)沿着通…...
使用 Auto-scheduling 优化算子
本篇回答来源于 TVM 官方英文文档 Lianmin Zheng,Chengfan Jia。更多 TVM 中文文档可访问→https://tvm.hyper.ai/ 本教程将展示 TVM 的 Auto Scheduling 功能,如何在不编写自定义模板的情况下,找到最佳 schedule。 与基于模板的 AutoTVM 依…...
智能运维应用之道,告别企业数字化转型危机
面临的问题及挑战 数据中心发展历程 2000 年中国数据中心始建,至今已经历以下 3 大阶段。早期:离散型数据中心 IT 因以项目建设为导向,故缺乏规划且无专门运维管理体系,此外,开发建设完的项目均是独立运维维护&#…...
第七章 SQL错误信息 - SQL错误代码 -400 到 -500
文章目录第七章 SQL错误信息 - SQL错误代码 -400 到 -500SQL错误代码和消息表WinSock错误代码-10050到-11002第七章 SQL错误信息 - SQL错误代码 -400 到 -500 SQL错误代码和消息表 错误代码描述-400发生严重错误-401严重连接错误-402用户名/密码无效-405无法从通信设备读取-4…...
DDFN: Decoupled Dynamic Filter Networks解耦的动态卷积
一、论文信息 论文名称:Decoupled Dynamic Filter Networks 论文:https://thefoxofsky.github.io/files/ddf.pdf 代码:https://github.com/theFoxofSky/ddfnet 主页:https://thefoxofsky.github.io/project_pages/ddf 作者团…...
NISP认证报名条件是什么?考试内容是什么?
科学技术是社会发展的第一生产力,每个国家为了能够获得更高的国际地位,不断提升自己的科学技术,现代最为先进的技术就是信息通信,在军事、民生、医疗、教育、制造等等领域都起着重要的作用,我们的生活也因为信息技术而…...
利用redis实现缓存、发布订阅、分布式锁功能
Redis是一个内存键值存储数据库,通常用于缓存、会话管理、消息队列等场景。以下是一些常见的Redis使用场景:1.缓存:将常用的数据缓存在Redis中,以减少对数据库的访问次数,提高应用程序的性能。2.会话管理:使…...
SVN无法连接到服务器的各种问题原因及解决办法
SVN专业使用教程详解 第一节 安装VisualSVN Server服务器 第一步 下载SVN服务器,需要链接的请私信。 点击下载的执行文档进行安装 选择组件 选择在部署 VisualSVN Server 时安装VisualSVN Server 和 Administration Tools 组件。 调整初始服务器配置 或者&…...
React 基本使用
目录 React 安装 React基本使用 React脚手架 脚手架使用React JSX基本使用 JSX列表渲染 JSX条件渲染 JSX模板精简 JSX样式控制 JSX综合案例 React 安装 npm i react react-domnpm init -y(生成基础目录文件) <!-- 引入js文件 --><sc…...
单例模式设计(面试题)
1、static修饰变量规则static修饰的静态成员属于 类而不是对象,所有的对象共享一份静态成员数据,所以不占用类的空间static修饰的成员,定义类的时候,必须分配空间static修饰的静态成员数据 必须类中定义 类外初始化静态成员变量可…...
机器学习:基于支持向量机(SVM)进行人脸识别预测
机器学习:基于支持向量机(SVM)进行人脸识别预测 文章目录机器学习:基于支持向量机(SVM)进行人脸识别预测一、实验目的二、实验原理三、实验环境四、实验内容五、实验步骤1.准备数据2.业务理解3.数据理解4.数…...
【服务器数据恢复】多块磁盘离线导致RAIDZ崩溃的数据恢复案例
服务器数据恢复环境: SUN ZFS系列某型号存储阵列; 40块磁盘组建的存储池(其中4块磁盘用作全局热备盘),池内划分出若干空间映射到服务器使用; 服务器使用Windows操作系统。 服务器故障: 服务器在…...
iconfont 图标如何在uniapp中的tabBar使用
注意: 小程序并不支持tabBar中 设置 iconfont 1. 材料准备 首先进入字体图标网址:iconfont-阿里巴巴矢量图标库;(如果你没有登入,记得登入一下) 把图标添加入购物车 添加到购物车之后-(右上角…...
第六章.卷积神经网络(CNN)—卷积层(Convolution)池化层(Pooling)
第六章.卷积神经网络(CNN) 6.1 卷积层(Convolution)&池化层(Pooling) 1.整体结构 以5层神经网络的实现为例: 1).基于全连接层(Affine)的网络 全连接层:相邻层的所有神经元之间都有连接 2).常见的CNN的网络 3).全连接层存在的问题 数据的形状容易被…...
c/c++开发,无可避免的模板编程实践(篇六)
一、泛型算法 1.1 泛型算法概述 c标准库不仅包含数据结构(容器、容器适配器等),还有很多算法。数据结构可以帮助存放特定情况下需要保存的数据,而算法则会将数据结构中存储的数据进行变换。标准库没有给容器添加大量的功能函数&am…...
【Java】Spring核心与设计思想
文章目录Spring核心与设计思想1. Spring是什么1.1 什么是容器1.2 什么是IOC1.2.1 传统程序开发1.2.2 控制反转式程序开发1.2.3 对比总结规律1.3 理解Spring IOC1.4 DI概念说明Spring核心与设计思想 1. Spring是什么 我们通常所说的Spring指的是Spring Framework(S…...
组合实现多类别分割(含实战代码)
来源:投稿 作者:AI浩 编辑:学姐 摘要 segmentation_models_pytorch是一款非常优秀的图像分割库,albumentations是一款非常优秀的图像增强库,这篇文章将这两款优秀结合起来实现多类别的图像分割算法。数据集选用CamVid…...
从红队视角看AWD攻击
AWD的权限维持 攻防兼备AWD模式是一种综合考核参赛团队攻击、防御技术能力、即时策略的比赛模式。在攻防模式中,参赛队伍分别防守同样配置的虚拟靶机,并在有限的博弈时间内,找到其他战队的薄弱环节进行攻击,同时要对自己的靶机环…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15
缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下: struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
五子棋测试用例
一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏,有着深厚的文化底蕴。通过将五子棋制作成网页游戏,可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家,都可以通过网页五子棋感受到东方棋类…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...
