在前一篇文章中简单封装了int类型的Slice,并且通过基准测试得出性能远远高于 reflect.DeepEqual
。
本章将封装一个通用的包比较各种值类型的slice,在已知slice值类型时使用。
思路分析
- 定义一个 interface 名为
Interface
,包含两个方法:len()
返回slice的长度,item()
根据索引获取值 - 定义
compare
方法,接收两个实现了Interface
的 slice ,进行比较。 - 定义类型
StringSlice
用于比较string类型;IntSlice
用于比较int类型;int64、float64、float32 等类似。
实现示例
新建文件: path/compare/slice.go
,以 string 和 int 类型为例,实现封装。
package compare
type Interface interface {
// len方法返回集合中的元素个数
Len() int
// item方法根据索引返回集合的值
Item(idx int) interface{}
}
type IntSlice []int
func (p IntSlice) Len() int { return len(p) }
func (p IntSlice) Item(idx int) interface{} { return p[idx] }
func Ints(a, b []int) bool {
return Compare(IntSlice(a), IntSlice(b))
}
type StringSlice []string
func (p StringSlice) Len() int { return len(p) }
func (p StringSlice) Item(idx int) interface{} { return p[idx] }
func Strings(a, b []string) bool {
return Compare(StringSlice(a), StringSlice(b))
}
// compare 循环遍历比较两个集合
// 先比较两个集合的长度是否相等
// 再循环遍历每一个元素进行比较
func Compare(a, b Interface) bool {
if a.Len() != b.Len() {
return false
}
if (a == nil) != (b == nil) {
return false
}
for i := 0; i < a.Len(); i++ {
if a.Item(i) != b.Item(i) {
return false
}
}
return true
}
调用示例
package main
import (
"./compare"
"fmt"
)
func main() {
s1 := []string{"h", "e", "l", "l", "o"}
s2 := []string{"h", "e", "l", "l", "o"}
if compare.Strings(s1, s2) {
fmt.Println("equal..") // equal...
} else {
fmt.Println("not equal!")
}
}
性能测试
新建文件: path/compare/slice_test.go
package compare
import (
"reflect"
"testing"
)
var (
slice1 = []string{"foo", "bar", "h", "e", "l", "l", "o"}
slice2 = []string{"foo", "bar", "h", "e", "l", "l", "oooo"}
)
func BenchmarkStrings(b *testing.B) {
for i := 0; i < b.N; i++ {
Strings(slice1, slice2)
}
}
func BenchmarkRelfectDeepEqual(b *testing.B) {
for i := 0; i < b.N; i++ {
reflect.DeepEqual(slice1, slice2)
}
}
Benchmark测试结果:
BenchmarkStrings-4 2000000 705 ns/op
BenchmarkRelfectDeepEqual-4 1000000 1254 ns/op
使用包
代码已封装推送到github,在项目中可以直接使用。
拉取项目代码
go get -u -v github.com/gushasha/go-learn
使用示例
package main
import (
"fmt"
"github.com/gushasha/go-learn/compare"
)
func main() {
s1 := []string{"h", "e", "l", "l", "o"}
s2 := []string{"h", "e", "l", "l", "o"}
if compare.Strings(s1, s2) {
fmt.Println("equal..")
} else {
fmt.Println("not equal!")
}
}
网友评论