go 不等于_Go 每日一库之 go-cmp

1fe453cf30ea88dc88dd37941c406ee8.png

简介

我们时常有比较两个值是否相等的需求,最直接的方式就是使用==操作符,其实==的细节远比你想象的多,我在深入理解 Go 之==中有详细介绍,有兴趣去看看。但是直接用==,一个最明显的弊端就是对于指针,只有两个指针指向同一个对象时,它们才相等,不能进行递归比较。为此,reflect包提供了一个DeepEqual,它可以进行递归比较。但是相对的,reflect.DeepEqual不够灵活,无法提供选项实现我们想要的行为,例如允许浮点数误差。所以今天的主角go-cmp登场了。go-cmp是 Google 开源的比较库,它提供了丰富的选项。最初定位是用在测试中。

感谢thinkgos的推荐!

快速使用

先安装:

$ go get github.com/com/google/go-cmp/cmp

后使用:

package main

import (
  "fmt"

  "github.com/google/go-cmp/cmp"
)

type Contact struct {
  Phone string
  Email string
}

type User struct {
  Name    string
  Age     int
  Contact *Contact
}

func main() {
  u1 := User{Name: "dj", Age: 18}
  u2 := User{Name: "dj", Age: 18}

  fmt.Println("u1 == u2?", u1 == u2)
  fmt.Println("u1 equals u2?", cmp.Equal(u1, u2))

  c1 := &Contact{Phone: "123456789", Email: "dj@example.com"}
  c2 := &Contact{Phone: "123456789", Email: "dj@example.com"}

  u1.Contact = c1
  u2.Contact = c1
  fmt.Println("u1 == u2 with same pointer?", u1 == u2)
  fmt.Println("u1 equals u2 with same pointer?", cmp.Equal(u1, u2))

  u2.Contact = c2
  fmt.Println("u1 == u2 with different pointer?", u1 == u2)
  fmt.Println("u1 equals u2 with different pointer?", cmp.Equal(u1, u2))
}

上面的例子中,我们将==cmp.Equal放在一起做个比较:

  • 在指针类型的字段Contact未设置时,u1 == u2cmp.Equal(u1, u2)都返回true
  • 两个结构的Contact字段都指向同一个对象时,u1 == u2cmp.Equal(u1, u2)都返回true
  • 两个结构的Contact字段指向不同的对象时,尽管这两个对象包含相同的内容,u1 == u2也返回了false。而cmp.Equal(u1, u2)可以比较指针指向的内容,从而返回true

以下是运行结果:

u1 == u2? true
u1 equals u2? true
u1 == u2 with same pointer? true
u1 equals u2 with same pointer? true
u1 == u2 with different pointer? false
u1 equals u2 with different pointer? true

高级选项

未导出字段

默认情况下,cmp.Equal()函数不会比较未导出字段(即字段名首字母小写的字段)。遇到未导出字段,cmp.Equal()直接panic。这一点与reflect.DeepEqual()有所不同,后者也会比较未导出的字段。

我们可以使用cmdopts.IgnoreUnexported选项忽略未导出字段,也可以使用cmdopts.AllowUnexported选项指定某些类型的未导出字段需要比较。

package main

import (
  "fmt"

  "github.com/google/go-cmp/cmp"
)

type Contact struct {
  Phone string
  Email string
}

type User struct {
  Name    string
  Age     int
  contact *Contact
}

func main() {
  c1 := &Contact{Phone: "123456789", Email: "dj@example.com"}
  c2 := &Contact{Phone: "123456789", Email: "dj@example.com"}

  u1 := User{"dj", 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值