Golang中如何判断两个Slice是否相等?


Golang中如何判断两个Slice是否相等?

文章插图
在 Golang 中,要判断两个 slice 是否相等是不能直接使用 == 运算符的(== 只能说明 两个 slice 是否指向同一个底层数组) 。如果两个 slice 的底层数组相同,但长度或容量不同,则仍然不相等;反之,如果两个 slice 的底层数组不同,即使有相同的元素也不相等 。因此,为了判断两个 slice 是否相等,需要比较它们的元素 。
循环遍历比较下面是一种比较 slice 是否相等的通用方法,需要遍历两个 slice 内的元素并进行逐个比较:
package mainfunc equalWithLoop(a, b []int) bool {if len(a) != len(b) { // 长度不同,直接返回 falsereturn false}if (a == nil) != (b == nil) {return false}for i, v := range a { // 每个元素逐一比较if v != b[i] {return false}}return true}首先,通过 len 函数比较长度,如果长度不同,那么肯定不相等,直接返回 false 。然后,把 []int{} != []int(nil) 这种情况也考虑进去 。最后使用 for 循环逐一比较每个元素,如果发现有不相等的元素,返回 false,如果遍历结束后没有发现不相等的元素,返回 true 。
需要注意的是,这种方法只适用于切片元素是可比较类型的情况 。如果切片元素是结构体等不可比较类型,则需要使用 reflect.DeepEqual 函数来比较两个切片是否相等 。
reflect比较可以使用 reflect.DeepEqual() 函数来进行比较,这个函数会递归比较两个 slice 中的元素,如果完全相同,则返回true,否则返回false 。示例代码如下:
package mainimport "reflect"func equalWithReflect(a, b []int) bool {return reflect.DeepEqual(a, b)}这种方法虽然很简洁,但是由于使用了反射和递归,效率比较低 。
两种方法效率对比接下来使用Benchmark来简单测试下两种方法的效率,编写测试代码如下:
package mainimport "testing"func BenchmarkEqualWithLoop(b *testing.B) {sa := []int{1, 3, 5, 7, 9}sb := []int{2, 4, 6, 8, 0}b.ResetTimer()for n := 0; n < b.N; n++ {equalWithLoop(sa, sb)}}func BenchmarkEqualWithReflect(b *testing.B) {sa := []int{1, 3, 5, 7, 9}sb := []int{2, 4, 6, 8, 0}b.ResetTimer()for n := 0; n < b.N; n++ {equalWithReflect(sa, sb)}}在测试文件所在目录运行如下命令
go test -bench=.在我电脑上运行结果如下
luduoxin$ go test -bench=.goos: darwingoarch: amd64pkg: test/cmpcpu: Intel(R) Core(TM) i5-8259U CPU @ 2.30GHzBenchmarkEqualWithLoop-810000000000.8794 ns/opBenchmarkEqualWithReflect-86162374196.2 ns/opPASSokhello/slice2.847s可以看出reflect方式要慢上几个数量级 。

【Golang中如何判断两个Slice是否相等?】


    推荐阅读