Как сравнить структуру, срез, карту равны?



Я хочу, чтобы проверить, что две структуры равны, но есть некоторые проблемы:



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

728   3  

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

    Ничего не найдено.