我想检查两个结构是否相等,但有一些问题:
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)
}
Run Code Online (Sandbox Code Playgroud)
One*_*One 134
你可以使用reflect.DeepEqual,或者你可以实现自己的函数(性能明智比使用反射更好):
http://play.golang.org/p/CPdfsYGNy_
m1 := map[string]int{
"a":1,
"b":2,
}
m2 := map[string]int{
"a":1,
"b":2,
}
fmt.Println(reflect.DeepEqual(m1, m2))
Run Code Online (Sandbox Code Playgroud)
Col*_*tel 49
reflect.DeepEqual 经常被错误地用于比较两个类似的结构,就像你的问题一样.
cmp.Equal 是比较结构的更好工具.
要了解为什么反思是不明智的,让我们看看文档:
如果导出和未导出的相应字段非常相等,则结构值非常相等.
....
数字,bools,字符串和通道 - 如果使用Go的==运算符相等则非常相等.
如果我们比较time.Time相同UTC时间的两个值,t1 == t2如果它们的元数据时区不同,则将为false.
go-cmp查找Equal()方法并使用它来正确比较时间.
例:
m1 := map[string]int{
"a": 1,
"b": 2,
}
m2 := map[string]int{
"a": 1,
"b": 2,
}
fmt.Println(cmp.Equal(m1, m2)) // will result in true
Run Code Online (Sandbox Code Playgroud)
wst*_*wst 15
自2017年7 月起,您可以使用cmp.Equalwithcmpopts.IgnoreFields选项。
func TestPerson(t *testing.T) {
type person struct {
ID int
Name string
}
p1 := person{ID: 1, Name: "john doe"}
p2 := person{ID: 2, Name: "john doe"}
println(cmp.Equal(p1, p2))
println(cmp.Equal(p1, p2, cmpopts.IgnoreFields(person{}, "ID")))
// Prints:
// false
// true
}
Run Code Online (Sandbox Code Playgroud)
Ili*_*oly 14
这是你如何推出自己的功能http://play.golang.org/p/Qgw7XuLNhb
func compare(a, b T) bool {
if &a == &b {
return true
}
if a.X != b.X || a.Y != b.Y {
return false
}
if len(a.Z) != len(b.Z) || len(a.M) != len(b.M) {
return false
}
for i, v := range a.Z {
if b.Z[i] != v {
return false
}
}
for k, v := range a.M {
if b.M[k] != v {
return false
}
}
return true
}
Run Code Online (Sandbox Code Playgroud)
与下面相同,但maps.Equal现在位于标准库中,您可以直接使用它,而不必导入实验包或滚动自己的包。
该提案(https://github.com/golang/go/issues/47649)是 Go 泛型未来实现的一部分,引入了一个新函数来比较两个映射maps.Equal:
// Equal reports whether two maps contain the same key/value pairs.
// Values are compared using ==.
func Equal[M1, M2 constraints.Map[K, V], K, V comparable](m1 M1, m2 M2) bool
Run Code Online (Sandbox Code Playgroud)
使用示例
strMapX := map[string]int{
"one": 1,
"two": 2,
}
strMapY := map[string]int{
"one": 1,
"two": 2,
}
equal := maps.Equal(strMapX, strMapY)
// equal is true
Run Code Online (Sandbox Code Playgroud)
maps包位于golang.org/x/exp/maps. 这是实验性的,超出了 Go 兼容性保证。他们的目标是将其移至 Go 1.19 中的标准库中
你可以看到它在 gotip Playground 中工作 https://gotipplay.golang.org/p/M0T6bCm1_3m
| 归档时间: |
|
| 查看次数: |
88797 次 |
| 最近记录: |