文档:https://pkg.go.dev/github.com/google/go-cmp/cmp
与reflect.DeepEqual 相比,它提供了自定义比较方式,另外如果是在测试中,它可以返回可读性较高的两个值之间的差异。

Func

  1. // Diff返回一个人类可读的关于两个值之间差异的报告:y - x。
  2. // 当且仅当Equal对相同的输入值和选项返回true时,它返回一个空字符串。
  3. func Diff(x, y interface{}, opts ...Option) string
  4. // 它的行为与reflect.DeepEqual比较类似
  5. // 基本数据类型,如bool,int,float,complex numbers,string, channel 相当于 '=='
  6. // Func 只有两者都是 nil 时相等
  7. // Struct 递归判断每个字段Equal,如果包含未导出字段且没有忽略它,或导致恐慌
  8. // Slice 相同索引处的元素“深度”相等, non-nil 和 nil slice不相等
  9. // Map key 指向的value 相等, non-nil 和 nil map不相等
  10. // Pointer 两者存储的具体值“深度”相等
  11. func Equal(x, y interface{}, opts ...Option) bool
  1. package main
  2. import (
  3. "fmt"
  4. "github.com/google/go-cmp/cmp"
  5. )
  6. type Persion struct {
  7. Name string
  8. Age uint
  9. }
  10. func main() {
  11. p1 := Persion{"zhangsan",10}
  12. p2 := Persion{"zhangsan",20}
  13. diff := cmp.Diff(p1,p2)
  14. fmt.Println(diff)
  15. }
  16. --------------------------------output-----------------------------------
  17. main.Persion{
  18. Name: "zhangsan",
  19. - Age: 10,
  20. + Age: 20,
  21. }

type Option

  1. func AllowUnexported(types ...interface{}) Option // 允许比较指定的未导出类型
  2. func Exporter(f func(reflect.Type) bool) Option // 允许对哪些未导出字段进行比较
  3. /*
  4. // 允许对所有未导出字段进行比较
  5. diff := cmp.Diff(p1,p2,cmp.Exporter(func(r reflect.Type) bool {
  6. return true
  7. }))
  8. */
  9. func Comparer(f interface{}) Option // 自定义比较器,f必须是 func(T, T) bool 类型
  10. func Ignore() Option // 不进行比较
  11. // FilterPath返回一个新的Option,只有f返回true时,opt才会生效
  12. // 传入的选项可以是Ignore、Transformer、Comparer、Options或先前过滤过的option
  13. func FilterPath(f func(Path) bool, opt Option) Option

type Path

  1. type Path []PathStep
  2. func (pa Path) GoString() string // 使用Go语法返回特定节点的路径
  3. func (pa Path) Index(i int) PathStep
  4. func (pa Path) Last() PathStep
  5. func (pa Path) String() string

type PathStep

  1. type PathStep interface {
  2. String() string
  3. Type() reflect.Type
  4. Values() (vx, vy reflect.Value)
  5. }

一个复杂的例子

  1. func main() {
  2. p1 := NewPersion("zhangsan",10)
  3. p2 := NewPersion("zhangsan",20)
  4. // 当匹配到指定的path,我们将其转交给cmp.Comparer 做比较
  5. diff := cmp.Diff(p1,p2,cmp.FilterPath(func(path cmp.Path) bool {
  6. fmt.Println(path.String())
  7. fmt.Println(path.Last().String())
  8. fmt.Println(path.GoString())
  9. if path.String() == "Age" {
  10. return true
  11. }
  12. return false
  13. },cmp.Comparer(func(x,y uint) bool {
  14. return true
  15. })))
  16. fmt.Println(diff)
  17. }
  18. --------------------------------output-----------------------------------
  19. Name
  20. .Name
  21. {main.Persion}.Name
  22. Age
  23. .Age
  24. {main.Persion}.Age