1

I am comparing two slices, both of type []int. One is coming in to API in the form of json and parsed as go struct. In the struct, it is intialized as empty []int{}. Second is saved in the database (MongoDb) and is fetched and mapped to same struct type.

In some cases, the two slices are completely blank. But comparison is returning false.

reflect.DeepEqual(oldSettings.S1, newSettings.S1)

I have also checked both fields type using reflect.TypeOf(newSettings.S1). It is retuning []int for both.

Please consider this playground link for structure example.

https://play.golang.org/p/1JTUCPImxwq

type OldSettings struct {
    S1 []int
}

type NewSettings struct {
    S1 []int
}

func main() {
    oldSettings := OldSettings{}
    newSettings := NewSettings{}

    if reflect.DeepEqual(oldSettings.S1, newSettings.S1) == false {
        fmt.Println("not equal")
    } else {
        fmt.Println("equal")
    }
}

Thanks!

icza
  • 389,944
  • 63
  • 907
  • 827
Amandeep kaur
  • 985
  • 3
  • 15
  • 35

1 Answers1

7

reflect.DeepEqual() returns false if one slice is nil, and the other is a non-nil slice with 0 length. Quoting from doc of reflect.DeepEqual():

Slice values are deeply equal when all of the following are true: they are both nil or both non-nil, they have the same length, and either they point to the same initial entry of the same underlying array (that is, &x[0] == &y[0]) or their corresponding elements (up to length) are deeply equal. Note that a non-nil empty slice and a nil slice (for example, []byte{} and []byte(nil)) are not deeply equal.

Example:

oldSettings := OldSettings{S1: []int{}}
newSettings := NewSettings{}

if reflect.DeepEqual(oldSettings.S1, newSettings.S1) == false {
    fmt.Println("not equal")
} else {
    fmt.Println("equal")
}

This outputs (try it on the Go Playground):

not equal

If the S1 field is not present in your JSON or MongoDB source, after unmarshaling it will be left nil. But if it exists as an empty array, an empty, non-nil slice will be created for it in Go.

Example proving it:

var s struct {
    S1 []int
}

if err := json.Unmarshal([]byte(`{}`), &s); err != nil {
    panic(err)
}
fmt.Println(s, s.S1 == nil)

if err := json.Unmarshal([]byte(`{"S1":[]}`), &s); err != nil {
    panic(err)
}
fmt.Println(s, s.S1 == nil)

Which outputs (try it on the Go Playground):

{[]} true
{[]} false
icza
  • 389,944
  • 63
  • 907
  • 827