为了账号安全,请及时绑定邮箱和手机立即绑定

为什么 go-cmp Equal() 说结构不是深度相等,即使所有字段都深度相等?

为什么 go-cmp Equal() 说结构不是深度相等,即使所有字段都深度相等?

Go
达令说 2022-12-05 11:16:28
我一直在reflect.DeepEqual使用循环指针来深入比较结构。由于这不适用于地图和更好的测试输出,我已经切换到go-cmp.现在我必须注意,即使cmp.Equal应该是 的替代品reflect.DeepEqual,但在前者正常工作的情况下,在这种情况下会有不同的结果,即使它实际上非常相等。谁能告诉我为什么在这种情况下结果不同,理想情况下如何解决?Go playground 中的代码:https: //play.golang.com/p/rLWKwMlAfwu (更新为使用 fmt.Printf(),因为我无法testing在 playground 中运行)差异输出:StrongConnect() mismatch (-want +got):  &⟪ref#0⟫main.Edge{    StartNode: &⟪ref#1⟫main.Node{        Variable: 1,-       Low:      &⟪ref#0: 0xc00005c120⟫(...),+       Low:      &⟪ref#0: 0xc00005c120⟫(...),        High:     &{StartNode: &⟪ref#1⟫(...), EndNode: &{Variable: 2}, EdgeType: 1, Weight: 1},    },    EndNode:  &{Variable: 2},    EdgeType: 0,    Weight:   1,  }
查看完整描述

1 回答

?
长风秋雁

TA贡献1757条经验 获得超7个赞

reflect.DeepEqualcmp.Equal比将结构与循环进行比较时更宽松(并且可以说是不正确的)。

cmp.Equal如果图中的节点和边集相同,则只会认为重叠图是等效的。注意NodeEdgestruct 都是此图比较中的节点。

在您的示例中,2 个图形/结构重叠但wantEdge0有一个额外的Edge结构作为根节点(前置)。

这是数据结构中循环的缩减表示:

wantEdge0 := &main.Edge{   // n0

    StartNode: &main.Node{ // n1

        Low: &main.Edge{}  // n2

    },

}

wantEdge0.StartNode.Low.StartNode = wantEdge0.StartNode // n1

got := wantEdge0.StartNode.Low                          // n2

因此有两个不同的周期:

  1. wantEdge0 [n0] -> wantEdge0.StartNode [n1] -> got [n2] -> wantEdge0.StartNode [n1]

  2. got [n2] -> wantEdge0.StartNode [n1] -> got [n2]

reflect.DeepEqual这是一个简单的例子,演示了和之间的区别cmp.Equal

package main


import (

    "fmt"

    "reflect"


    "github.com/google/go-cmp/cmp"

)


type Node struct {

    Next  *Node

    Value int

}


func main() {

    a0 := &Node{}

    a1 := &Node{}

    a2 := &Node{}

    a0.Next = a1

    a1.Next = a2

    a2.Next = a1


    b1 := &Node{}

    b2 := &Node{}

    b1.Next = b2

    b2.Next = b1


    fmt.Println("DeepEqual\tcmp.Equal")

    fmt.Printf("\t%v\t%v\t\tIndependent graphs\n", reflect.DeepEqual(a1, b1), cmp.Equal(a1, b1))

    fmt.Printf("\t%v\t%v\t\tSame graph, different root\n", reflect.DeepEqual(a1, a2), cmp.Equal(a1, a2))

    fmt.Printf("\t%v\t%v\t\tSame graph prepend vs no prepend\n", reflect.DeepEqual(a0, a1), cmp.Equal(a0, a1))

}

输出:


$ ./compare 

DeepEqual   cmp.Equal

    true    true        Independent graphs

    true    true        Same graph, different root

    true    false       Same graph prepend vs no prepend

解决方案:我建议为您想要的结构和测试输入分配完全独立的结构。这样want和got结构就不会重叠,它们应该按预期进行比较。


查看完整回答
反对 回复 2022-12-05
  • 1 回答
  • 0 关注
  • 117 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号