本文讨论下Go中对象比较,分别为==
、第三方包github.com/google/go-cmp/cmp中cmp.Equal()
方法、reflect.DeepEqual()
以及自定义isEqual()
方法。
1. 环境准备
为了演示,这里定义简单Person结构体以及NewPerson方法创建对象。
type Person struct {
Name string
Age int
}
func NewPerson(name string, age int) *Person {
return &Person{
Name: name,
Age: age,
}
}
接着在main函数中创建两个对象,然后分别调用不同的比较方法:
func main() {
Admin1 := NewPerson("Admin", 18)
Admin2 := NewPerson("Admin", 18)
Compare1(Admin1, Admin2)
Compare2(Admin1, Admin2)
Compare3(Admin1, Admin2)
IsEqual(Admin1, Admin2)
}
我们再定义衡量执行函数,用于比较性能:
func execTime(compareType string, start time.Time) {
var elapsed = time.Since(start)
log.Printf("%s took %s \n", compareType, elapsed)
}
2.使用 == 比较
直接使用==
,我们知道这实际在比较对象地址,不会相等。
func Compare1(p1 , p2 *Person) {
defer execTime("'==' took ", time.Now())
if p1 == p2{
fmt.Printf("== \n")
} else {
fmt.Printf("!= \n")
}
}
3.使用cmp.Equal()
库
func Compare2(p1 , p2 *Person) {
defer execTime("cmp.Equal took ", time.Now())
if cmp.Equal(p1,p2) {
fmt.Printf("== \n")
} else {
fmt.Printf("!= \n")
}
}
这里是比较对象内容,结果相等。
4.使用reflect.DeepEqual()
func Compare3(p1 , p2 *Person) {
defer execTime("DeepEqual took ", time.Now())
if reflect.DeepEqual(p1, p2){
fmt.Printf("== \n")
} else {
fmt.Printf("!= \n")
}
}
这种方式也是比较对象属性值,结果相等。
5.自定义比较方法
func IsEqual(A, B interface{}) bool {
defer execTime("IsEqual took", time.Now())
// Find out the type of A & B is Person or not
if _, ok := A.(*Person); ok {
if _, ok := B.(*Person); ok {
if A.(*Person).Name == B.(*Person).Name {
fmt.Printf("== \n")
return A.(*Person).Age == B.(*Person).Age
} else {
return false
}
}
return false
}
return false
}
方法首先检查参数类型,然后依次比较对象属性值。
2. 运行结果与效率
运行结果与之前预期一致,除了第一种方法不相等,其他都相等。同时我们观察执行时间,平均比较还是自定义效率比较高。
2020/07/09 20:44:20 '==' took took 8.0004ms
2020/07/09 20:44:21 cmp.Equal took took 16.0009ms
2020/07/09 20:44:21 DeepEqual took took 1.0001ms
2020/07/09 20:44:21 IsEqual took took 0s
3. 总结
本文介绍了四种Golang的对象比较方法,其中==
只能比较对象地址,不能比较属性值是否相等。其他三种方法能够比较对象属性值,从执行效率来看,自定义比较方式有优势。