How to compare struct, slice, map are equal?

I want to check that the two structures are equal, but have some problems:

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

+92
go go-reflect
Jul 02 '14 at 14:41
source share
3 answers

You can use reflect.DeepEqual , or you can implement your own function (which will be better than using 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)) 
+128
Jul 02 '14 at
source share

reflect.DeepEqual often misused to compare two similar structures, as in your question.

cmp.Equal is the best tool for comparing structures.

To understand why reflection is not recommended, review the documentation :

Struct values ​​are deeply equal if their respective fields, both exported and unexported, are deeply equal.

....

numbers, bools, strings and channels are deeply equal if they are equal using the Go == operator.

If we compare two time.Time values ​​of the same UTC time, t1 == t2 will be false if they are the time zone of the metadata.

go-cmp looks for the Equal() method and uses it to correctly compare time.

Example:

 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 
+43
Jul 20 '17 at 18:24
source share

Here is how you would apply your own function http://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 } 
+14
Jul 02 '14 at 15:00
source share



All Articles