Как сравнить структуру, срез, карту равны?
Я хочу, чтобы проверить, что две структуры равны, но есть некоторые проблемы:
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)
}
3 ответов:
можно использовать отразить.DeepEqual, или вы можете реализовать свою собственную функцию (какая производительность будет лучше, чем использование отражения):
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часто неправильно используется для сравнения двух подобных структур, как в вашем вопросе.
cmp.Equalявляется лучшим инструментом для сравнения структур.чтобы понять, почему отражение не рекомендуется, давайте посмотрим на документация:
значения структуры глубоко равны, если их соответствующие поля, как экспортированные, так и не экспортированные, глубоко равны.
....
номера, bools, строки и каналы-это глубоко равны, если они равны, используя оператор Go==.
если сравнить два
time.Timeзначения того же времени UTC,t1 == t2будет false, если они метаданные часовой пояс отличается.
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
вот как вы бы свернули свою собственную функцию 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 }
Comments