十分钟掌握Go语言==运算符与reflect.DeepEqual函数处理interface{}值的比较规则
在 Go 语言中,interface{} 类型是一种特殊的接口类型,它表示任意类型的值。你可以使用 == 运算符来检测任意两个 interface{} 类型值的相等性,比较的规则和一般的接口类型一样,需要满足以下条件:
- 两个 interface{} 值的动态类型必须相同,也就是说,它们存储的具体类型必须一致。
- 两个 interface{} 值的动态值必须相等,也就是说,它们存储的具体值必须可以比较的。
根据 Go 语言规范的描述,interface{} 类型的值在内存中是由两个字(word)组成的,一个字存储了动态类型的信息,另一个字存储了动态值的信息。如果动态值的大小超过了一个字,那么这个字就存储了动态值的指针,指向实际的动态值。
Go 编译器是如何判定 interface{} 值是否相等的呢?
使用 == 符号比较两个 interface{} 类型的值时,Go编译器会先比较它们的动态类型,也就是比较它们的第一个字,看是否指向相同的类型信息。如果不相同直接返回 false,如果相同,则继续比较它们的动态值,也就是比较它们的第二个字,看是否相等。如果动态值的大小超过了一个字,那么这个字就是一个指针,需要根据指针找到实际的动态值,并且根据动态类型的规则进行比较。
例如,如果动态类型是数组,那么就需要逐个比较数组的元素,如果动态类型是结构体,那么就需要逐个比较结构体的字段,以此类推。
下面是一个简单的例子,演示了如何使用 == 符号比较两个 interface{} 类型的值:
package mainimport "fmt"func main() {var a, b interface{}// 给 a 赋值为 int64 类型的 1a = int64(1)// 给 b 赋值为 int64 类型的 2b = int64(2)// a和b的动态类型相同, 动态值不同, 输出结果为 falsefmt.Println(a == b) // false// 给 b 赋值为 int64 类型的 1b = int64(1)// a和b的动态类型相同, 动态值也相同, 此时输出结果为truefmt.Println(a == b) // true// 给 b 赋值为 float32 类型的 1b = float32(1)// 此时a和b的动态类型不相同, 就不会进行动态值的处理, 输出结果为falsefmt.Println(a == b) // false// 给 a,b 赋值为 int 类型的数组a = [5]int{1, 2, 3, 4, 5}b = [5]int{1, 2, 3, 4, 5}fmt.Println(a == b) // true// 给 b 赋值为 int 类型的数组b = [5]int{1, 2, 3, 4, 6}fmt.Println(a == b) // false// 给 b 赋值为 int 类型的切片b = []int{1, 2, 3, 4, 5}// 此时a和b的动态类型已然不相同, 就不会进行动态值的处理, 输出结果为falsefmt.Println(a == b) // false// 给 a 赋值为 int 类型的切片a = []int{1, 2, 3, 4, 5}// 此时a和b的动态类型和动态值虽然相同, 但是在Go语言中切片类型的值是不能用 == 符号比较,会引发运行时错误//fmt.Println(a == b) // panic: runtime error: comparing uncomparable type []int
}
== 运算符通常只能用于比较基本类型和支持 == 操作的复合类型,如数组、结构体等,而不能用于比较切片、映射、函数等类型,否则会引发编译错误或运行时错误。
那么问题来了,如果一定要比较两个切片、映射、函数的相等性,该如何操作呢?
reflect.DeepEqual 函数原型:
// 用于判断两个值是否深度一致
//
// 除了类型相同;在可以时(主要是基本类型)会使用==;但还会比较array、slice的成员,
// map的键值对,结构体字段进行深入比对。map的键值对,对键只使用==,但值会继续往深
// 层比对。DeepEqual函数可以正确处理循环的类型。函数类型只有都会nil时才相等;空切
// 片不等于nil切片;还会考虑array、slice的长度、map键值对数。
func DeepEqual(x, y any) bool
对于 reflect.DeepEqual 而言,它通过牺牲程序的性能来弥补 == 运算符无法处理切片、映射、函数的短板,对于不支持 == 操作的类型,reflect.DeepEqual 函数会有一套自己的比较规则。
你可以把 reflect.DeepEqual 函数理解成是 == 运算符的扩展版!下面是一个简单的例子,演示了如何使用 reflect.DeepEqual 函数:
package mainimport "fmt"func main() {var a, b interface{}// 给 a 赋值为 int64 类型的 1a = int64(1)// 给 b 赋值为 int64 类型的 2b = int64(2)fmt.Println(a == b, reflect.DeepEqual(a, b))b = int64(1)fmt.Println(a == b, reflect.DeepEqual(a, b))b = float32(1)fmt.Println(a == b, reflect.DeepEqual(a, b))// 给 b 赋值为 int 类型的切片a, b = []int{1, 2, 3, 4, 5}, []int{1, 2, 3, 4, 5}fmt.Println(reflect.DeepEqual(a, b)) // trueb = []int{5, 4, 3, 2, 1}fmt.Println(reflect.DeepEqual(a, b)) // false
}
相关文章:
十分钟掌握Go语言==运算符与reflect.DeepEqual函数处理interface{}值的比较规则
在 Go 语言中,interface{} 类型是一种特殊的接口类型,它表示任意类型的值。你可以使用 运算符来检测任意两个 interface{} 类型值的相等性,比较的规则和一般的接口类型一样,需要满足以下条件: 两个 interface{} 值的…...

Unity3d Shader篇(一)— 顶点漫反射着色器解析
文章目录 前言一、顶点漫反射着色器是什么?1. 顶点漫反射着色器的工作原理 二、编写顶点漫反射着色器1. 定义属性2. 创建 SubShader3. 编写着色器程序段4. 完成顶点着色器5. 完成片段着色器 三、效果四、总结 前言 在 Unity 中,Shader 可以用来实现各种…...

WordPress主题YIA的文章页评论内容为什么没有显示出来?
有些WordPress站长使用YIA主题后,在YIA主题设置的“基本”中没有开启“一键关闭评论功能”,而且文章也是允许评论的,但是评论框却不显示,最关键的是文章原本就有的评论内容也不显示,这是为什么呢? 根据YIA主…...

选择低代码应该注意什么?如何选择?
我查看了几乎所有的介绍低代码的总结和分析报告,几乎都没有把低代码最底层的产品逻辑说清楚。今天我尝试不用复杂的技术名词,也不用代码,把这个事儿给大家说明白,低代码到底怎么回事儿!(人云亦云那些&#…...

橘子学linux调优之工具包的安装
今天在公司无聊的弄服务器,想着有些常用的工具包安装一下,这里就简单记录一下。 一、sysstat的安装和使用 1、安装 我是通过源码的方式安装的,这样的好处在于可以自由选择你的版本,很直观。 直接去github上找到sysstat的地址&a…...

函数的连续与间断【高数笔记】
【连续】 分类,分几个?每类特点? 连续条件,是同时满足还是只需其一? 【间断】 分类,分几个大类,又分几个小类?每类特点? 间断条件,是同时满足还是只需其一&am…...
游戏如何选择服务器
选择游戏服务器是一个综合性的过程,涉及到的因素包括但不限于游戏类型和规模、硬件配置、网络质量、安全性、服务商的声誉以及地理分布等。以下是一些具体的指导原则: 游戏类型和规模:根据游戏的具体需求来选择合适的服务器。例如࿰…...
ubuntu20安装mysql8
1.安装 sudo apt update sudo apt install mysql-server-8.0 -y2.查看运行状态 yantaoubuntu20:~$ sudo systemctl status mysql ● mysql.service - MySQL Community ServerLoaded: loaded (/lib/systemd/system/mysql.service; enabled; vendor preset:>Active: active …...

07 SB3之@HttpExchange(TBD)
HttpExchange是SpringBoot3的新特性. Spring Boot3 提供了新的 HTTP 的访问能力,封装了Http底层细节. 通过接口简化 HTTP远程访问,类似 Feign 功能。 SpringBoot 中定义接口提供 HTTP 服务 --> 框架生成的代理对象实现此接口 --> 框架生成的代理…...
Redis数据淘汰策略
Redis作为一种高性能的键值存储数据库,通常用于缓存和提高数据检索速度。然而,由于内存资源有限,当内存不足以容纳所有数据时,Redis就需要采取一些策略来删除部分数据,以确保新的数据能够被写入。这就引入了数据淘汰策…...

Git的一些基本操作
初始git 我们给出下面的一个场景,在大学里,一些老师在我们做完实验之后喜欢让我们交实验报告,假设我们有一个比较追求完美的老师和一个勤奋的学生,这个学生叫做小帅,那天小帅桑勤奋的完成实验报告,在第二天…...
Spring Boot中异步线程池@Async
很多业务场景需要使用异步去完成,比如:发送短信通知。要完成异步操作一般有两种: 1、消息队列MQ 2、线程池处理。 我们来看看Spring框架中如何去使用线程池来完成异步操作,以及分析背后的原理。 一. Spring异步线程池的接口类 …...

ArcGIS学习(五)坐标系-2
3.不同基准面坐标系之间的转换 在上一关中,我们学习了ArcGIS中的投影(投影栅格)工具,并以"WGS1984地理坐标系与WGS1984的UTM投影坐标系的转换”为例进行讲解。 "WGS1984地理坐标系与WGS1984的UTM投影坐标系的转换”代表的是同一个基准面下的两个坐标的转换。 …...

2024Node.js零基础教程(小白友好型),nodejs新手到高手,(五)NodeJS入门——http模块
044_http模块_创建HTTP服务端 hello,大家好,那这个小节我们来使用 nodejs 创建一个 http 的服务,有了这个 http 服务之后,我们就可以处理浏览器所发送过来的请求,并且还可以给这个浏览器返回响应。 顺便说一下&#x…...
sklearn.preprocessing 标准化、归一化、正则化
文章目录 数据标准化的原因作用归一化最大最小归一化针对规模化有异常的数据标准化线性比例标准化法log函数标准化法正则化Normalization标准化的意义数据标准化的原因 某些算法要求样本具有零均值和单位方差;需要消除样本不同属性具有不同量级时的影响: ① 数量级的差异将导…...
Windows系统编程(一) 文件与目录操作
以下程序需要包含<Windows.h>头文件 创建打开文件 HANDLE hFile CreateFile("D:\\rkvir.ini", GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 此处打开文件,参数依次 已有文件的路径,注意…...

6-2、T型加减速计算简化【51单片机+L298N步进电机系列教程】
↑↑↑点击上方【目录】,查看本系列全部文章 摘要:本节介绍简化T型加减速计算过程,使其适用于单片机数据处理。简化内容包括浮点数转整型数计算、加减速对称处理、预处理计算 一、浮点数转整型数计算 根据上一节内容已知 常用的晶振大小…...

配置Jenkins自动构建打包项目
转载说明:如果您喜欢这篇文章并打算转载它,请私信作者取得授权。感谢您喜爱本文,请文明转载,谢谢。 需求说明 1、给A项目配置jenkins每2小时无条件自动构建一次,无论是否有代码提交。 2、给B项目配置jenkins每15分钟检…...

进阶C语言-通讯录的实现
通讯录 🎈1.设计要求🎈2.程序实现🔭2.1打印菜单及初始化通讯录🔭2.2显示所有联系人🔭2.3查找指定的联系人🔭2.4删除指定的联系人🔭2.5查找指定的联系人🔭2.6修改指定联系人🔭2.7按照年龄排序(以此为例)🎈3.全部源码以及实现🎈1.设计要求 🌞通过前面…...

STM32单片机的基本原理与应用(七)
超声波测距实验 基本原理 超声波测距实验是STM32单片机通过控制HC-SR04超声波模块,使其发送超声波,遇到物体反射回超声波来实现距离测量,其原理就是在发射超声波到接收超声波会有一段时间,而超声波在空气中传播的速度为声速&…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...

企业大模型服务合规指南:深度解析备案与登记制度
伴随AI技术的爆炸式发展,尤其是大模型(LLM)在各行各业的深度应用和整合,企业利用AI技术提升效率、创新服务的步伐不断加快。无论是像DeepSeek这样的前沿技术提供者,还是积极拥抱AI转型的传统企业,在面向公众…...

如何在Windows本机安装Python并确保与Python.NET兼容
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...

AxureRP-Pro-Beta-Setup_114413.exe (6.0.0.2887)
Name:3ddown Serial:FiCGEezgdGoYILo8U/2MFyCWj0jZoJc/sziRRj2/ENvtEq7w1RH97k5MWctqVHA 注册用户名:Axure 序列号:8t3Yk/zu4cX601/seX6wBZgYRVj/lkC2PICCdO4sFKCCLx8mcCnccoylVb40lP...