我想检查两个结构体、切片和Map是否相等。
但是我在下面的代码中遇到了问题。请参阅我在相关行的评论。
package main
import (
"fmt"
"reflect"
)
type T struct {
X int
Y string
Z []int
M map[string]int
}
func main() {
t1 := T{
X: 1,
Y: "lei",
Z: []int{1, 2, 3},
M: map[string]int{
"a": 1,
"b": 2,
},
}
t2 := T{
X: 1,
Y: "lei",
Z: []int{1, 2, 3},
M: map[string]int{
"a": 1,
"b": 2,
},
}
fmt.Println(t2 == t1)
//error - invalid operation: t2 == t1 (struct containing []int cannot be compared)
fmt.Println(reflect.ValueOf(t2) == reflect.ValueOf(t1))
//false
fmt.Println(reflect.TypeOf(t2) == reflect.TypeOf(t1))
//true
//Update: slice or map
a1 := []int{1, 2, 3, 4}
a2 := []int{1, 2, 3, 4}
fmt.Println(a1 == a2)
//invalid operation: a1 == a2 (slice can only be compared to nil)
m1 := map[string]int{
"a": 1,
"b": 2,
}
m2 := map[string]int{
"a": 1,
"b": 2,
}
fmt.Println(m1 == m2)
// m1 == m2 (map can only be compared to nil)
}
7条答案
按热度按时间q5lcpyga1#
你可以使用reflect.DeepEqual,或者你可以实现你自己的函数(这比使用反射更好):
http://play.golang.org/p/CPdfsYGNy_
z8dt9xmd2#
reflect.DeepEqual
经常被错误地用来比较两个类似的结构体,就像你的问题中那样。cmp.Equal
是比较结构体的更好工具。要了解为什么反射是不明智的,让我们看看文档:
如果结构值的相应字段(包括导出的和未导出的字段)完全相等,则结构值完全相等。
....
numbers、bool、string和channels -如果使用Go的==运算符相等,则深度相等。
如果我们比较两个相同UTC时间的
time.Time
值,如果它们的元数据时区不同,则t1 == t2
将为false。go-cmp
查找Equal()
方法并使用该方法正确比较时间。范例:
重要提示:
使用
cmp.Equal
时要小心,因为它是may lead to a panic condition它只用于测试,因为性能不是目标,如果不能比较值,它可能会死机。它的恐慌倾向意味着它不适合生产环境,在那里虚假的恐慌可能是致命的。
mjqavswn3#
下面是如何滚动自己的函数http://play.golang.org/p/Qgw7XuLNhb
更新:Go 1.18
jogvjijk4#
如果你打算在测试中使用它,由于July 2017,你可以使用
cmp.Equal
和cmpopts.IgnoreFields
选项。fcg9iug35#
如果您在单元测试**中比较它们,一个方便的替代方法是testify中的EqualValues函数。
y1aodyip6#
如果你想比较简单的一级结构,最好和最简单的方法是
if
语句。像这样
if s1 == s2
举个简单的例子:
结果:
u1 is equal to u2
你可以玩这个here。
mi7gmzs67#
Go 1.21
和下面一样,但是
maps.Equal
现在在标准库中,你可以直接使用它,而不是导入实验性的软件包或自己开发。转到1.18 ~ 1.20
这个提议(https://github.com/golang/go/issues/47649)是Go泛型未来实现的一部分,它引入了一个新函数来比较两个map,
maps.Equal
:示例使用
maps
软件包位于golang.org/x/exp/maps
中。这是实验性的,超出了Go兼容性保证。他们的目标是将其移动到Go 1.19的标准库中你可以在gotip playground https://gotipplay.golang.org/p/M0T6bCm1_3m中看到它的工作