我一直在使用reflect.DeepEqual来深入比较使用循环指针的 struct .由于这不适用于 map 和更好的测试输出,我已经切换到go-cmp.

现在我必须注意到,虽然cmp.Equal应该是reflect.DeepEqual的替代品,但如果前者正确工作,那么在这种情况下,会有不同的结果,尽管它实际上是非常相等的.

有人能告诉我为什么在这种情况下结果不同,以及理想情况下,如何修复它吗?

围棋场代码:https://play.golang.com/p/rLWKwMlAfwu

差异的输出:

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,
  }

推荐答案

当将 struct 与周期进行比较时,reflect.DeepEqualcmp.Equal更宽松(可以说是不正确的).

如果图中的 node 和边的集合是相同的,那么cmp.Equal将只考虑重叠图等价.Note:NodeEdge struct 都是此图比较中的 node .

在您的示例中,两个图形/ struct 重叠,但wantEdge0 is有一个额外的Edge struct 作为根 node (带前缀).

以下是数据 struct 中周期的简化表示:

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.DeepEqualcmp.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

Solution:我建议为want struct 和测试输入分配完全独立的 struct .这样wantgot struct 就不会重叠,它们应该按预期进行比较.

参考资料:

Go相关问答推荐

Golang ==错误:OCI运行时创建失败:无法启动容器进程:exec:./" bin:stat./" bin:没有这样的文件或目录:未知

Kafka消费者在需要时不会暂停

仅呈现一个模板的GIN Web应用程序

在GO中使用泛型类型 struct 实现接口方法

Docker Compose Health Check未退出,错误为无法启动

如何用';贪婪原则';正确地

如果第一次匹配条件,如何跳过切片中的值

Go:为什么我不能比较 net.Addr

Exchange Web 服务 - 使用 soap xml 请求查找所有未读邮件

golang 上基于标头的版本控制

如何在 Go 中编写示例测试?

Golang:如何判断通过缓冲通道进行通信时生产者或消费者是否较慢?

如何使用 fyne Go 使用 canvas.NewText() 使文本可滚动

Protobuf.Any - 从 json.RawMessage 解组

在 Gorm 的 AfterFind() 钩子中获取智能 Select struct 的值

Golang invopop jsonschema 使用 if/then/else

使用 package`regexp` 查找 Golang 中的所有 mactch 子字符串,但得到意外结果

gorm 获取列名

GoLang 遍历 yaml 文件

HCL 解码:具有多个标签的块