0 喜欢

Go使用Reflect.DeepEqual比较数据结构

admin
admin
2021-08-02 00:47:43 阅读 247

介绍

当我刚开始使用 Go 时,我通常会通过编写一个 for 循环来迭代比较两个切片是否相等。在看到一些包含使用 Reflect 包的示例代码后,我意识到这完全没有必要。我们可以通过将 SlicesMapsStructs 简单地传递给 reflect.DeepEqual(x,y) 来比较它们。

Slice/Array 示例

让我们编写一个实现反转切片的函数:

func ReverseSlice(s []string) []string {
	reverseSlice := make([]string, len(s))

	for l, i := len(s), 0; l > 0; l, i = l-1, i+1 {
		reverseSlice[i] = s[l-1]
	}

	return reverseSlice
}

现在,我们为这个函数编写测试用例

package main

import (
	"reflect"
	"testing"
)

func TestReverseSlice(t *testing.T) {
	got := ReverseSlice([]string{"0004", "0003", "0002", "0001"})

	want := []string{"0001", "0002", "0003", "0004"}

	if !reflect.DeepEqual(got, want) {
		t.Errorf("got %q slice but expected %q", got, want)
	}
}

是不是非常简单!但是,需要注意的是,两个数组的顺序必须相同,这一点非常重要。它们不能具有相同的值,但是顺序却不同。函数注释特别说明:Array values are deeply equal when their corresponding elements are deeply equal.

Map 示例

Map 有点不同,默认情况下,它们具有特定顺序。

那么它们如何比较 DeepEqual 呢?它们的地址都需要为 nil 或不为 nil,具有相同的长度和键/值对。

在这种情况下,我将使用 fmt.Printf 打印语句来展示其中的一些要点:

func main() {
    m1, m2 := make(map[string]string), make(map[string]string)

    m1["person1"] = "person1"
    m1["person2"] = "person2"

    m2["person2"] = "person2"
    m2["person1"] = "person1"

    fmt.Printf("type=%T -- addr=%p -- len=%d\n", m1, &m1, len(m1))
    fmt.Printf("type=%T -- addr=%p -- len=%d\n", m2, &m2, len(m2))

    if reflect.DeepEqual(m1, m2) {
        fmt.Println("they are equal")
    } else {
        fmt.Println("they are NOT equal")
    }
}

具体来说,我们希望比较 Map 的类型、地址和长度。我们需要类型和长度相同,但地址应该不同(但不是 nil)。

运行后,您应该会看到类似于以下内容的输出:

type=map[string]string -- addr=0xc0000b0018 -- len=2
type=map[string]string -- addr=0xc0000b0020 -- len=2
they are equal

参考链接

Using reflect.DeepEqual to compare data structures in Go


关于作者
admin
admin
admin@ifront.net
 获得点赞 44
 文章阅读量 46076
文章标签