golang反射(reflect)虽爽,但很贵

news2024/10/7 17:10:39

标准库 reflect 为 Go 语言提供了运行时动态获取对象的类型和值以及动态创建对象的能力。反射可以帮助抽象和简化代码,提高开发效率。

但是使用反射势必会多出大量的操作指令,导致性能下降

案例

字段赋值方式对比

 type Student struct {
     Name   string
     Id     int32
     Addr   string
     Number string
 }func BenchmarkSetStudentValue(b *testing.B) {
     student := new(Student)
     b.ResetTimer()
     for i := 0; i < b.N; i++ {
         student.Name = "张三"
         student.Id = 10
         student.Addr = "缅甸"
         student.Number = "10086"
     }
 }func BenchmarkSetStudentValueByField(b *testing.B) {
     typ := reflect.TypeOf(Student{})
     v := reflect.New(typ).Elem()
     b.ResetTimer()
     for i := 0; i < b.N; i++ {
         v.Field(0).SetString("张三")
         v.Field(1).SetInt(10)
         v.Field(2).SetString("缅甸")
         v.Field(3).SetString("10086")
     }
 }func BenchmarkSetStudentValueByFieldName(b *testing.B) {
     typ := reflect.TypeOf(Student{})
     v := reflect.New(typ).Elem()
     b.ResetTimer()
     for i := 0; i < b.N; i++ {
         v.FieldByName("Name").SetString("张三")
         v.FieldByName("Id").SetInt(10)
         v.FieldByName("Addr").SetString("缅甸")
         v.FieldByName("Number").SetString("10086")
     }
 }

可以看出反射所带来的性能消耗是非常大的,如果使用FieldByName用字段名赋值还会多出一部分通过字段名映射字段索引的反射操作流程,导致性能比使用Field还要劣化17倍左右。
在这里插入图片描述

考虑优化

这里可以优化一下,自己维护一个字典

 func BenchmarkSetStudentValueByFieldNameCache(b *testing.B) {
     typ := reflect.TypeOf(Student{})
     v := reflect.New(typ).Elem()
     cache := make(map[string]int, typ.NumField())
     for i := 0; i < typ.NumField(); i++ {
         cache[typ.Field(i).Name] = i
     }
     b.ResetTimer()
     
     for i := 0; i < b.N; i++ {
         v.Field(cache["Name"]).SetString("张三")
         v.Field(cache["Id"]).SetInt(10)
         v.Field(cache["Addr"]).SetString("缅甸")
         v.Field(cache["Number"]).SetString("10086")
     }
 }

可以看到,快了不少,比直接使用FieldByName,优化了5倍多。
在这里插入图片描述

让人眼前一亮的unsafe

顺便提一下先前说的unsafe包,在这个场景下也有用武之地

 func BenchmarkSetStudentValueByUnsafe(b *testing.B) {
     student := new(Student)
     pStudent := unsafe.Pointer(student)
     b.ResetTimer()
     for i := 0; i < b.N; i++ {
         pNameStudent := (*string)(unsafe.Pointer(uintptr(pStudent) + unsafe.Offsetof(student.Name)))
         *pNameStudent = "张三"
         pIdStudent := (*int)(unsafe.Pointer(uintptr(pStudent) + unsafe.Offsetof(student.Id)))
         *pIdStudent = 10
         pAddrStudent := (*string)(unsafe.Pointer(uintptr(pStudent) + unsafe.Offsetof(student.Addr)))
         *pAddrStudent = "缅甸"
         pNumberStudent := (*string)(unsafe.Pointer(uintptr(pStudent) + unsafe.Offsetof(student.Number)))
         *pNumberStudent = "10086"
     }
 }

可以看到,它的性能表现和直接赋值不相上下,让人眼前一亮
在这里插入图片描述

总结

反射在一些场景下非常方便,使代码看起来更加简洁精炼,易维护,但同时它带来的性能损耗也是昂贵的。因此能不用反射尽量不用反射,如果一定要用反射,考虑是否可以做一些优化。

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

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

相关文章

centos7中的管道和重定向

重定向 0 标准输入 1 标准输出 2 标准错误 3 进程在执行的过程中打开的其他文件 & 标准正确和标准错误的混合输出 输出重定向 &g…

[C/C++]——内存管理

学习C/C的内存管理 前言&#xff1a;一、C/C的内存分布二、C语言中动态内存管理方式三、C中动态内存管理方式3.1、new/delete操作符3.1.2、new/delete操作内置类型3.1.3、new/delete操作自定义类型 3.2、认识operator new和operator delete函数3.3、了解new和delete的实现原理3…

修改Element UI可清空Input的样式

如图所示&#xff0c;修改Input右侧的清空按钮位置&#xff1a; <el-input class"create-catalog-ipt"placeholder"请输入相关章节标题"v-model"currentCatalogTitle"clearable /> // SCSS环境 ::v-deep {.create-catalog-ipt {input {he…

web前端项目-影视网站开发

影视网站 本项目主要使用到了 HTML&#xff1b;CSS&#xff1b;JavaScript脚本技术&#xff1b;AJAX无刷新技术&#xff1b;jQuery等技术实现了动态影视网页 运行效果&#xff1a; 一&#xff1a;index.html <!DOCTYPE> <html lang"en"> <head>…

【01分数规划】ABC324F

[ABC324F] Beautiful Path - 洛谷 思路 首先看到这个形式很容易想到 01 分数规划&#xff0c;即去二分答案&#xff0c;然后就是转化成 是否存在一个路径使得 sigma b - mid * sigma c > 0 显然只需要改变一下边权&#xff0c;跑一遍最长路即可 #include <bits/stdc.h…

招聘网站爬虫及可视化的实现-计算机毕业设计推荐 django

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

docker-compose Install gitea

gitea 前言 Gitea 是一个轻量级的 DevOps 平台软件。从开发计划到产品成型的整个软件生命周期,他都能够高效而轻松的帮助团队和开发者。包括 Git 托管、代码审查、团队协作、软件包注册和 CI/CD。它与 GitHub、Bitbucket 和 GitLab 等比较类似。 Gitea 最初是从 Gogs 分支而来…

C语言小游戏之三子棋(可以做期末设计作业)

哈喽大家好&#xff0c;今天为大家带来一个用C语言写的小游戏--三子棋&#xff0c;就是大家小时候用树枝和石子玩的那种游戏&#xff0c;这个小项目可以用于大家的C语言期末设计作业&#xff0c;不会很难&#xff0c;都是C语言基本的操作 下面是游戏截图&#xff1a; 完全可以…

C语言写的 mini版的 http 服务器 , 很详细

文章目录 效果展示整体架构流程技术细节完整代码 效果展示 例如&#xff1a;htpp://192.168.23.140/home.html -> 正确的请求格式 home.html 这个资源是放在我们服务器里面的 , 并不是随便访问的资源,当然我们可以放很多的资源进去. 整体架构流程 整个实现的流…

2 接口测试实战演示

上一篇&#xff1a;1 接口测试介绍-CSDN博客 拿到开发提供的接口文档后&#xff0c;结合需求文档开始做接口测试用例设计&#xff0c;下面用最常见也最简单的注册功能介绍整个流程。 说明&#xff1a;以演示接口测试流程为主&#xff0c;不对演示功能做详细的测试&#xff0c;…

法语 Alt 代码表

法语的 Alt 代码表&#xff0c;请参考下图。 输入方法就是按住 Alt 键不松开&#xff0c;然后在小键盘上输入字符&#xff0c;松开 Al 键&#xff0c;计算机就能输出上面的字符了。 西班牙语 Alt 代码表 - 系统容器 - iSharkFly西班牙语 Alt 代码表&#xff0c;请参考下图。 输…

(第6天)RHEL 8 安装单机 Oracle 19C CDB 数据库

RHEL 8 安装单机 Oracle 19C 数据库(第6天) 随着 Oracle 版本的升级,硬件也在不断更新迭代,为了迎合这种趋势,Linux 系统也在不断升级,目前已经更新至 8 代版本。相信不久的将来,Linux 8 和 Oracle 19C 将成为主流版本,因此不得不讲 Linux 8 如何安装 Oracle 19C 数据…

javaWebssh汽车销售管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh汽车销售管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用 B/S模式开发。开发环境为TOMCAT7.…

群晖(Synology)新建存储池使用 Home 服务

每一个用户都可以有一个自己的 Home 服务。 这个在群晖存储新建存储池后可以自动启用这个服务。 启用后&#xff0c;可以看到你的文件系统中有一个 homes 的文件了。 群晖&#xff08;Synology&#xff09;新建存储池使用 Home 服务 - 系统容器 - iSharkFly每一个用户都可以有…

ubuntu将本机的wifi网络通过网线分享给另一台机器(用于没有有线网络,重装系统后无wifi驱动或者另一台设备没有wifi网卡)

1.将两台机器通过网线连接 2.在pci ethernet中设置选择另一台机器的mac address&#xff0c;ipv4中选择share to other computer&#xff0c;另一台机器上设置为动态ip&#xff0c;连接上之后另一台机器即可上网。

分层解耦—三层架构

目录 三层架构 分层解耦 IOC&DI 三层架构 在进行程序设计以及程序开发时&#xff0c;尽可能让每一个接口、类、方法的职责更单一些&#xff08;单一职责原则&#xff09;。 单一职责原则&#xff1a;一个类或一个方法&#xff0c;就只做一件事情&#xff0c;只管一块功…

已解决:No goals have been specified for this build. You must specify a vali

[ERROR] No goals have been specified for this build. You must specify a valiTOC 完整报错 No goals have been specified for this build. You must specify a valid lifecycle phase or a goal in the format : or :[:]:. Available lifecycle phases are: pre-clean, c…

【IC前端虚拟项目】MVU模块方案与背景熟悉

【IC前端虚拟项目】数据搬运指令处理模块前端实现虚拟项目说明-CSDN博客 mvu这个模块是干嘛用的呢&#xff1f;从这个名字就可以看出来move_unit&#xff0c;应该是做数据搬运的。很多指令级中都会有数据搬运的指令&#xff0c;这类指令的作用一般是在片内片外缓存以及通用专用…

网络安全项目实战(三)--报文检测

6. TCP/IP协议栈及以太网帧 目标 了解TCP/IP协议栈的组织结构掌握以太网帧的数据格式定义能应用编码实现以太网帧的解析方法 6.1. TCP/IP 协议栈 TCP/IP网络协议栈分为应用层&#xff08;Application&#xff09;、传输层&#xff08;Transport&#xff09;、网络层&#xf…

使用Python监控服务器在线状态

前言 在公司内网有一台服务器&#xff0c;有动态的公网IP&#xff0c;使用DDNS对外提供服务&#xff0c;但是会因为停电、服务器卡死等原因导致服务器离线。服务器离线后无法及时获知&#xff0c;因此需要实现在服务器离线的时候能够发送消息到手机上。 思路梳理 公司办理的…