How to compare if two structs, slices or maps are equal?

后端 未结 5 2173
醉话见心
醉话见心 2020-11-28 02:30

I want to check if two structs, slices and maps are equal.

But I\'m running into problems with the following code. See my comments at the relevant lines.

<         


        
相关标签:
5条回答
  • 2020-11-28 02:53

    reflect.DeepEqual is often incorrectly used to compare two like structs, as in your question.

    cmp.Equal is a better tool for comparing structs.

    To see why reflection is ill-advised, let's look at the documentation:

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

    ....

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

    If we compare two time.Time values of the same UTC time, t1 == t2 will be false if their metadata timezone is different.

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

    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
    
    0 讨论(0)
  • 2020-11-28 03:04

    Here's how you'd roll your own function 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
    }
    
    0 讨论(0)
  • 2020-11-28 03:07

    You can use reflect.DeepEqual, or you can implement your own function (which performance wise would 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))
    
    0 讨论(0)
  • 2020-11-28 03:12

    Since July 2017 you can use cmp.Equal with cmpopts.IgnoreFields option.

    func TestPerson(t *testing.T) {
        type person struct {
            ID   int
            Name string
        }
    
        p1 := person{ID: 1, Name: "john doe"}
        p2 := person{ID: 2, Name: "john doe"}
        println(cmp.Equal(p1, p2))
        println(cmp.Equal(p1, p2, cmpopts.IgnoreFields(person{}, "ID")))
    
        // Prints:
        // false
        // true
    }
    
    0 讨论(0)
  • 2020-11-28 03:12

    If you're comparing them in unit test, a handy alternative is EqualValues function in testify.

    0 讨论(0)
提交回复
热议问题