reflect golang example go go-reflect

example - reflect golang



Cómo comparar struct, slice, map son iguales? (3)

Así es cómo implementarías tu propia función http://play.golang.org/p/Qgw7XuLNhb

func compare(a, b T) bool { if &a == &b { return true } if a.X != b.X || a.Y != b.Y { return false } if len(a.Z) != len(b.Z) || len(a.M) != len(b.M) { return false } for i, v := range a.Z { if b.Z[i] != v { return false } } for k, v := range a.M { if b.M[k] != v { return false } } return true }

Quiero comprobar que dos estructuras son iguales, pero tienen algún problema:

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


Puede usar reflect.DeepEqual , o puede implementar su propia función (que en cuanto a rendimiento sería mejor que usar 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))


reflect.DeepEqual menudo se usa incorrectamente para comparar dos estructuras similares, como en su pregunta.

cmp.Equal es una mejor herramienta para comparar estructuras.

Para ver por qué la reflexión no es recomendable, veamos la documentation :

Los valores de Struct son muy iguales si sus campos correspondientes, tanto exportados como no exportados, son profundamente iguales.

....

números, bools, cadenas y canales - son profundamente iguales si son iguales usando el operador == de Go.

Si comparamos dos valores time.Time del mismo tiempo UTC, t1 == t2 será falso si los metadatos de la zona horaria son diferentes.

go-cmp busca el método Equal() y lo usa para comparar tiempos correctamente.

Ejemplo:

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