简体   繁体   中英

reflect.DeepEqual() is returning false but slices are same

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!

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM