目录

slice相等的定义

判断两个[]byte是否相等

使用reflect判断slice是否相等

手写判断


在golang中我们可以轻松地通过==来判断两个数组(array)是否相等,但遗憾的是slice并没有相关的运算符,当需要判断两个slice是否相等时我们只能另寻捷径了。

slice相等的定义

我们选择最常见的需求,也就是当两个slice的类型和长度相同,且相等下标的值也是相等的,比如:

a := []int{1, 2, 3}
b := []int{1, 2, 3}
c := []int{1, 2}
d := []int{1, 3, 2}

上述代码中ab是相等的,c因为长度和a不同所以不相等,d因为元素的排列顺序和a不同所以也不相等。

判断两个[]byte是否相等

为什么要单独将[]byte列举出来呢?

因为标准库提供了优化的比较方案,不再需要我们造轮子了:

package mainimport ("bytes""fmt"
)func main() {a := []byte{0, 1, 3, 2}b := []byte{0, 1, 3, 2}c := []byte{1, 1, 3, 2}fmt.Println(bytes.Equal(a, b))fmt.Println(bytes.Equal(a, c))
}

运行结果如下:

使用reflect判断slice是否相等

在判断类型不是[]byte的slice时,我们还可以借助reflect.DeepEqual,它用于深度比较两个对象包括它们内部包含的元素是否都相等:

func DeepEqual(x, y interface{}) bool

DeepEqual reports whether x and y are “deeply equal,” defined as follows. Two values of identical type are deeply equal if one of the following cases applies. Values of distinct types are never deeply equal.
...
Slice values are deeply equal when all of the following are true: they are both nil or both non-nil, they have the same length, and either they point to the same initial entry of the same underlying array (that is, &x[0] == &y[0]) or their corresponding elements (up to length) are deeply equal. Note that a non-nil empty slice and a nil slice (for example, []byte{} and []byte(nil)) are not deeply equal.

这段话的意思不难理解,和我们在本文最开始时讨论的如何确定slice相等的原则是一样的,只不过它借助了一点运行时的“黑魔法”。

看例子:

package mainimport ("fmt""reflect"
)func main() {a := []int{1, 2, 3, 4}b := []int{1, 3, 2, 4}c := []int{1, 2, 3, 4}fmt.Println(reflect.DeepEqual(a, b))fmt.Println(reflect.DeepEqual(a, c))
}

手写判断

在golang中使用reflect通常需要付出性能代价,如果我们确定了slice的类型,那么自己实现slice的相等判断相对来说也不是那么麻烦:

func testEq(a, b []int) bool {// If one is nil, the other must also be nil.if (a == nil) != (b == nil) {return false;}if len(a) != len(b) {return false}for i := range a {if a[i] != b[i] {return false}}return true
}

测试代码:

package mainimport "fmt"func main() {a := []int{1, 2, 3, 4}b := []int{1, 3, 2, 4}c := []int{1, 2, 3, 4}fmt.Println(testEq(a, b))fmt.Println(testEq(a, c))
}

运行结果:

下面我们对后两种方案做个简单的性能测试,我们测试两个不相等但很相似的拥有20个元素的slice,这是在日常开发中较常见的情景:

func BenchmarkTestEq(b *testing.B) {a := []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}c := []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21}b.ResetTimer()for i := 0; i < b.N; i++ {_ = testEq(a, c)}
}func BenchmarkDeepEqual(b *testing.B) {a := []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}c := []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21}b.ResetTimer()for i := 0; i < b.N; i++ {_ = reflect.DeepEqual(a, c)}
}

当然这个测试只能反应出有限的信息,正常情况下应该给出更全面的测试用例。不过在我们的演示中反射仍然付出了惊人的性能代价:

如果我们把slice的长度设为1000,那么差距就会更加明显:

func genDiffSlice(size int) ([]uint32, []uint32) {a := make([]uint32, 0, size)rand.Seed(time.Now().UnixNano())for i := 0; i < size; i++ {a = append(a, rand.Uint32())}b := make([]uint32, len(a))copy(b, a)b[len(b)-1] = rand.Uint32()return a, b
}func BenchmarkTestEq2(b *testing.B) {a, c := genDiffSlice(1000)b.ResetTimer()for i := 0; i < b.N; i++ {_ = testEq(a, c)}
}func BenchmarkDeepEqual2(b *testing.B) {a, c := genDiffSlice(1000)b.ResetTimer()for i := 0; i < b.N; i++ {_ = reflect.DeepEqual(a, c)}
}

自己手写判断的性能更好,但是有个显而易见的弊端,当我们有多种类型的slice时我们就不得不编写不同版本的testEq,而它们唯一的不同仅仅只有slice的类型。

不过等到go2的泛型可以使用的时候,这样的弊端也就不复存在了,现在我们需要的是在代码的复杂度和运行性能上做出权衡。

golang 判断 两个slice 是否相等相关推荐

  1. go 判断元素是否在slice_golang 判断 两个slice 是否相等

    目录 在golang中我们可以轻松地通过==来判断两个数组(array)是否相等,但遗憾的是slice并没有相关的运算符,当需要判断两个slice是否相等时我们只能另寻捷径了. slice相等的定义 ...

  2. Golang如何遍历切片slice

    前言 这两天用golang开发一个把企业微信的打卡记录同步到HR-OA系统的一个中间表的功能,同步时把从企业微信接口里查询到的打卡记录放到一个对象的切片里,然后遍历切片把每条打卡记录写到中间表,这里涉 ...

  3. 判断两个树是否相等和判断tree1是否包含tree2 python实现

    判断两个树是否相等 def equal(node_a, node_b):"""判断两个树是否相等:param node_a: :param node_b: :return ...

  4. 判断两直线段是否相交

    转自:http://www.cnblogs.com/shengshouzhaixing/archive/2013/03/17/2964950.html //功能:求点在有向直线左边还是右边     / ...

  5. python中如何判断两个字符串是否相等_python怎样判断两个字符串是否相同

    原标题:python怎样判断两个字符串是否相同 python中,判断两个字符串是否相等或一样,可以使用==或者is来判断:判断不一样可以使用 is not. 示例 使用注意事项 1.有时候两个字符串打 ...

  6. 7_2判断两个单链表是否相交,若相交,求出第一个交点

    转载请注明出处:http://www.cnblogs.com/wuzetiandaren/p/4251372.html 声明:现大部分文章为寻找问题时在网上相互转载,此博是为自己做个记录记录,方便自己 ...

  7. 【GoLang】深入理解slice len cap什么算法? 参数传递有啥蹊跷?

    先上结论 1.内置append函数在现有数组的长度 < 1024 时 cap 增长是翻倍的,再往上的增长率则是 1.25,至于为何后面会说. 2.Go语言中channel,slice,map这三 ...

  8. java中判断两个字符(或者字符串相等)

    string a,b;//两字符串 在java中判断两个字符(字符串)相等,用a.equals(b); if(a.equals(b)){ //如果相等,返回值为true }else{ //如果不相等, ...

  9. 链表问题11——两个单链表相交的系列问题(三):判断两个有环链表是否相交

    题目 判断两个有环链表是否相交,相交则返回第一个相交节点,否则返回null 在考虑此问题时,根据前面几篇文章的解法,我们已经得到了各自链表的入环节点,分别为loop1和loop2 思路 以下是问题三的 ...

最新文章

  1. Python+selenium 自动化 - 实现自动导入、上传外部文件实例演示
  2. Android STL PORT
  3. CSS染色图标(图片)
  4. 产品经理应该mysql_数据库对产品经理的重要性
  5. MQ详解及四大MQ比较
  6. 【Python实例第12讲】谱系共聚类法
  7. 盘点国内外私募基金业绩报酬计提方式
  8. 文件对比工具 Beyond Compare 4.2.9中文破解版 附通用注册码
  9. 【计算机组成原理】学习笔记----第一章 计算机系统概述
  10. Python 爬虫实战(1):分析豆瓣中最新电影的影评
  11. mysql 查询字母集合_使用MySQL查询查找所有以字母“ a”,“ b”或“ c”开头的名称?...
  12. RRT_star MATLAB
  13. Redis第六讲 Redis之List底层数据结构实现
  14. [ROS](06)ROS通信 —— 话题(Topic)通信
  15. 【编程语言】Scala 函数式编程
  16. FreeFlyOS【十六】:file部分详解
  17. python中str()的使用
  18. 乳酪gi_Windows 8生产力:谁动了我的奶酪? 哦,是的。
  19. 单身情人节,看看这位Python小哥如何完成人生的逆袭!
  20. 编程手札:C++快速笔记

热门文章

  1. 互联网协议 — IPv4 — 分片与重组
  2. Kong APIGW — Plugins — Authentication
  3. Android各个文件夹对应的分辨率?
  4. 使用jquery实现的计算器功能
  5. [20170513]update结果集.txt
  6. foreach遍历打印表格
  7. pythoning ——3、数据类型(字符串)
  8. OSSIM系统用户审计
  9. 关于iOS7以后版本号企业公布问题
  10. UIViewController生命周期