【问题标题】:reflect.DeepEqual() is returning false but slices are samereflect.DeepEqual() 返回 false 但切片相同
【发布时间】:2020-11-02 10:04:25
【问题描述】:

我正在比较两个切片,都是[]int 类型。一种是以 json 的形式进入 API 并被解析为 go struct。在结构中,它被初始化为空[]int{}。第二个保存在数据库(MongoDb)中并被提取并映射到相同的结构类型。

在某些情况下,这两个切片是完全空白的。但比较返回false

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

我还使用reflect.TypeOf(newSettings.S1) 检查了这两个字段类型。它正在为两者重新调整 []int

请考虑这个游乐场链接作为结构示例。

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")
    }
}

谢谢!

【问题讨论】:

    标签: go slice reflect


    【解决方案1】:

    reflect.DeepEqual() 返回false,如果一个切片是nil,另一个是非nil 切片,长度为0。引用reflect.DeepEqual()的文档:

    当满足以下所有条件时,切片值是完全相等的:它们都是 nil 或都非 nil,它们具有相同的长度,并且它们指向同一底层数组的相同初始条目(即, &x[0] == &y[0]) 或它们对应的元素(直到长度)是完全相等的。请注意,非 nil 空切片和 nil 切片(例如,[]byte{} 和 []byte(nil))并不完全相等。

    例子:

    oldSettings := OldSettings{S1: []int{}}
    newSettings := NewSettings{}
    
    if reflect.DeepEqual(oldSettings.S1, newSettings.S1) == false {
        fmt.Println("not equal")
    } else {
        fmt.Println("equal")
    }
    

    这个输出(在Go Playground上试试):

    not equal
    

    如果您的 JSON 或 MongoDB 源中不存在 S1 字段,则在解组后将保留 nil。但如果它以空数组的形式存在,Go 中会为它创建一个空的、非nil 的切片。

    举例证明:

    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)
    

    哪些输出(在Go Playground 上试试):

    {[]} true
    {[]} false
    

    【讨论】:

      猜你喜欢
      • 2019-01-17
      • 1970-01-01
      • 2011-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-23
      • 1970-01-01
      相关资源
      最近更新 更多