文章插图
在 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是否相等?】
推荐阅读
- 如何确保自动化时代的网络安全和数据保护?
- 聊聊低代码平台如何选型
- mysql中的高级连接查询
- 如何设置自己的保护隐私的 DNS 服务器
- 数据中心结构化布线指南
- 在 SpringBoot 中使用 Spring AOP 实现接口鉴权
- Vue 3现实生活中的过渡和微互动
- HTTP缓存如何提高Web应用程序的性能?
- 华为工资是如何评定的?播报
- 第八批集采拟中选药品平均降价56% 预计每年可省167亿元