如何go语言比较两个对象是否深度相同
来源:脚本之家
时间:2023-01-07 11:56:39 236浏览 收藏
怎么入门Golang编程?需要学习哪些知识点?这是新手们刚接触编程时常见的问题;下面golang学习网就来给大家整理分享一些知识点,希望能够给初学者一些帮助。本篇文章就来介绍《如何go语言比较两个对象是否深度相同》,涉及到对象、go比较,有需要的可以收藏一下
前言:
func DeepEqual(x, y interface{}) bool
DeepEqual
函数的参数是两个 interface
,实际上也就是可以输入任意类型,输出 true 或者 flase 表示输入的两个变量是否是“深度”相等。
先明白一点,如果是不同的类型,即使是底层类型相同,相应的值也相同,那么两者也不是“深度”相等。
type MyInt int type YourInt int func main() { m := MyInt(1) y := YourInt(1) fmt.Println(reflect.DeepEqual(m, y)) // false }
上面的代码中,m, y 底层都是 int,而且值都是 1,但是两者静态类型不同,前者是 MyInt
,后者是 YourInt
,因此两者不是“深度”相等。
在源码里,有对 DeepEqual 函数的非常清楚地注释,列举了不同类型,DeepEqual 的比较情形,这里做一个总结:
类型 | 深度相等情形 |
---|---|
Array | 相同索引处的元素“深度”相等 |
Struct | 相应字段,包含导出和不导出,“深度”相等 |
Func | 只有两者都是 nil 时 |
Interface | 两者存储的具体值“深度”相等 |
Map | 1、都为 nil;2、非空、长度相等,指向同一个 map 实体对象,或者相应的 key 指向的 value “深度”相等 |
Pointer | 1、使用 == 比较的结果相等;2、指向的实体“深度”相等 |
Slice | 1、都为 nil;2、非空、长度相等,首元素指向同一个底层数组的相同元素,即 &x[0] == &y[0] 或者 相同索引处的元素“深度”相等 |
numbers, bools, strings, and channels | 使用 == 比较的结果为真 |
一般情况下,DeepEqual 的实现只需要递归地调用 == 就可以比较两个变量是否是真的“深度”相等。
但是,有一些异常情况:比如 func 类型是不可比较的类型,只有在两个 func 类型都是 nil 的情况下,才是“深度”相等;float 类型,由于精度的原因,也是不能使用 == 比较的;包含 func 类型或者 float 类型的 struct, interface, array 等。
对于指针而言,当两个值相等的指针就是“深度”相等,因为两者指向的内容是相等的,即使两者指向的是 func 类型或者 float 类型,这种情况下不关心指针所指向的内容。
同样,对于指向相同 slice, map 的两个变量也是“深度”相等的,不关心 slice, map 具体的内容。
对于“有环”的类型,比如循环链表,比较两者是否“深度”相等的过程中,需要对已比较的内容作一个标记,一旦发现两个指针之前比较过,立即停止比较,并判定二者是深度相等的。这样做的原因是,及时停止比较,避免陷入无限循环。
来看源码:
func DeepEqual(x, y interface{}) bool { if x == nil || y == nil { return x == y } v1 := ValueOf(x) v2 := ValueOf(y) if v1.Type() != v2.Type() { return false } return deepValueEqual(v1, v2, make(map[visit]bool), 0) }
首先查看两者是否有一个是 nil 的情况,这种情况下,只有两者都是 nil,函数才会返回 true
接着,使用反射,获取x,y 的反射对象,并且立即比较两者的类型,根据前面的内容,这里实际上是动态类型,如果类型不同,直接返回 false。
最后,最核心的内容在子函数 deepValueEqual
中。
代码比较长,思路却比较简单清晰:核心是一个 switch 语句,识别输入参数的不同类型,分别递归调用 deepValueEqual 函数,一直递归到最基本的数据类型,比较 int,string 等可以直接得出 true 或者 false,再一层层地返回,最终得到“深度”相等的比较结果。
实际上,各种类型的比较套路比较相似,这里就直接节选一个稍微复杂一点的 map
类型的比较:
// deepValueEqual 函数 // …… case Map: if v1.IsNil() != v2.IsNil() { return false } if v1.Len() != v2.Len() { return false } if v1.Pointer() == v2.Pointer() { return true } for _, k := range v1.MapKeys() { val1 := v1.MapIndex(k) val2 := v2.MapIndex(k) if !val1.IsValid() || !val2.IsValid() || !deepValueEqual(v1.MapIndex(k), v2.MapIndex(k), visited, depth+1) { return false } } return true // ……
和前文总结的表格里,比较 map 是否相等的思路比较一致,也不需要多说什么。说明一点,visited
是一个 map,记录递归过程中,比较过的“对”:
type visit struct { a1 unsafe.Pointer a2 unsafe.Pointer typ Type } map[visit]bool
比较过程中,一旦发现比较的“对”,已经在 map 里出现过的话,直接判定“深度”比较结果的是 true
。
好了,本文到此结束,带大家了解了《如何go语言比较两个对象是否深度相同》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多Golang知识!
-
451 收藏
-
336 收藏
-
262 收藏
-
247 收藏
-
358 收藏
-
233 收藏
-
322 收藏
-
181 收藏
-
316 收藏
-
244 收藏
-
300 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 507次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 484次学习
-
- 彩色的枕头
- 这篇文章内容太及时了,好细啊,很棒,mark,关注博主了!希望博主能多写Golang相关的文章。
- 2023-05-11 03:54:33
-
- 疯狂的网络
- 这篇博文出现的刚刚好,老哥加油!
- 2023-03-29 01:11:13
-
- 灵巧的短靴
- 感谢大佬分享,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢up主分享文章!
- 2023-03-01 00:15:26
-
- 可靠的帅哥
- 太细致了,收藏了,感谢作者的这篇技术贴,我会继续支持!
- 2023-02-23 00:38:21
-
- 落寞的唇彩
- 写的不错,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,帮助很大,总算是懂了,感谢作者大大分享文章内容!
- 2023-02-12 20:18:32
-
- 传统的书本
- 这篇文章内容太及时了,太全面了,很有用,收藏了,关注老哥了!希望老哥能多写Golang相关的文章。
- 2023-01-18 16:17:52
-
- 聪明的机器猫
- 好细啊,已收藏,感谢老哥的这篇文章内容,我会继续支持!
- 2023-01-16 16:46:46
-
- 有魅力的吐司
- 这篇技术贴太及时了,作者加油!
- 2023-01-15 22:31:37
-
- 聪慧的麦片
- 赞 👍👍,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢老哥分享技术文章!
- 2023-01-09 11:12:32
-
- 活力的小懒猪
- 这篇文章出现的刚刚好,太详细了,感谢大佬分享,已收藏,关注大佬了!希望大佬能多写Golang相关的文章。
- 2023-01-09 04:51:15