如何比较结构,切片,地图是否相等?
我想检查两个结构是否相等,但是有一些问题:
package main import ( "fmt" "reflect" ) type T struct { X int Y string Z []int M map[string]int } func main() { t1 := T{ X:1, Y:"lei", Z:[]int{1,2,3}, M:map[string]int{ "a":1, "b":2, }, } t2 := T{ X:1, Y:"lei", Z:[]int{1,2,3}, M:map[string]int{ "a":1, "b":2, }, } fmt.Println(t2 == t1) //error - invalid operation: t2 == t1 (struct containing []int cannot be compared) fmt.Println(reflect.ValueOf(t2) == reflect.ValueOf(t1)) //false fmt.Println(reflect.TypeOf(t2) == reflect.TypeOf(t1)) //true //Update: slice or map a1 := []int{1,2,3,4} a2 := []int{1,2,3,4} fmt.Println(a1==a2) //invalid operation: a1 == a2 (slice can only be compared to nil) m1 := map[string]int{ "a":1, "b":2, } m2 := map[string]int{ "a":1, "b":2, } fmt.Println(m1==m2) // m1 == m2 (map can only be compared to nil) }
http://play.golang.org/p/AZIzW2WunI
你可以使用reflect.DeepEqual ,或者你可以实现你自己的函数(性能明智比使用reflection更好):
http://play.golang.org/p/CPdfsYGNy_
m1 := map[string]int{ "a":1, "b":2, } m2 := map[string]int{ "a":1, "b":2, } fmt.Println(reflect.DeepEqual(m1, m2))
以下是你如何推出你自己的functionhttp://play.golang.org/p/Qgw7XuLNhb
func compare(a, b T) bool { if &a == &b { return true } if aX != bX || aY != bY { return false } if len(aZ) != len(bZ) || len(aM) != len(bM) { return false } for i, v := range aZ { if bZ[i] != v { return false } } for k, v := range aM { if bM[k] != v { return false } } return true }
reflect.DeepEqual
经常被错误地用来比较两个类似的结构,就像你的问题一样。
cmp.Equal
是比较结构的一个更好的工具。
要明白为什么reflection是不明智的,让我们看看文档 :
如果它们相应的字段(导出和未导出)深度相等,那么结构值是相等的。
….
数字,布尔,string和通道 – 如果使用Go的==运算符,它们是相等的。
如果我们比较两个time.Time
值相同的UTC时间, t1 == t2
将是假的,如果他们是元数据时区不同。
go-cmp
查找Equal()
方法并使用它来正确比较时间。
例:
m1 := map[string]int{ "a": 1, "b": 2, } m2 := map[string]int{ "a": 1, "b": 2, } fmt.Println(cmp.Equal(m1, m2)) // will result in true