介绍
当我刚开始使用 Go
时,我通常会通过编写一个 for
循环来迭代比较两个切片是否相等。在看到一些包含使用 Reflect
包的示例代码后,我意识到这完全没有必要。我们可以通过将 Slices 、Maps、Structs 简单地传递给 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