iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > GO >Golang怎么判断struct/slice/map是否相等
  • 758
分享到

Golang怎么判断struct/slice/map是否相等

2023-07-04 16:07:11 758人浏览 薄情痞子
摘要

这篇文章主要介绍“golang怎么判断struct/slice/map是否相等”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Golang怎么判断struct/slice/map是否相等”文章能帮助大

这篇文章主要介绍“golang怎么判断struct/slice/map是否相等”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Golang怎么判断struct/slice/map是否相等”文章能帮助大家解决问题。

    == 的对比方式

    == 适用的类型

    相信==判等操作,大家每天都在用。golang中对==的处理有一些细节的地方需要特别注意,==操作最重要的一个前提是:两个操作数类型必须相同!如果类型不同,那么编译时就会报错。

    示例代码:

    package mainimport "fmt"func main() {    var a int32    var b int64    // 编译错误:invalid operation a == b (mismatched types int32 and int64)    fmt.Println(a == b)}

    经常见到使用==的类型一般是:string,int等基本类型。struct有时候可以用有时候不可以。slicemap使用 ==会报错。

    slice和map使用 ==

    因为slice和map不止是需要比较值,还需要比较len和cap,层级比较深的话还需要递归比较,不是简单的==就可以比较的,所以他们各自之间是不可以直接用==比较的,slice和map只能和nil使用==。

    • 切片之间不允许比较。切片只能与nil值比较。

    • map之间不允许比较。map只能与nil值比较。

    s1 := []int64{1, 3}s2 := []int64{1, 2}if s1 == nil {} //编辑器不会提示报错if s1 == s2 {} //编辑器会提示报错

    channel使用 ==

    channel是引用类型,对比的是存储数据的地址。channel是可以使用==的,只要类型一样就可以。

    ch2 := make(chan int, 1)ch3 := ch2if cha2 == cha1{fmt.Println("true")} // true

    struct结构体使用==

    结构体的定义只是一种内存布局的描述,只有当结构体实例化时,才会真正地分配内存。

    实例化就是根据结构体定义的格式创建一份与格式一致的内存区域,结构体实例与实例间的

    内存是完全独立的。对结构体进行&取地址操作时,视为对该类型进行一次 new 的实例化操作

    因此:go中的结构体: v = Struct {}, v = &Struct{} 这个两种写法是等价的。

    • 简单结构的结构体,里面都是值类型或者指针的话,是可以使用 ==的

    • 结构体中含有slice或者map,都是不可以用==

    示例代码:

    package mainimport (    "fmt" )type User struct {    Name string    Age  int64}type People struct {    Name string    Hobby []string}func main() {        p1 := People{Name: "test", Hobby: []string{"唱", "跳"}}        p2 := People{Name: "test", Hobby: []string{"唱", "跳"}}        u1 := User{Name: "test", Age:18}u2 := User{Name: "test", Age:18}        if p1 == p2 {            fmt.Println("p1 ==  p2") //报错        }    if u1 == u2 {            fmt.Println("u1 ==  u2")        }    }

    reflect.DeepEqual() 和cmp.Equal()

    reflect.DeepEqual()

    reflect包提供的深度对比(递归)的方法,适用于go中的slice,map,struct,function的对比。

    对比规则

    • 相同类型的值是深度相等的,不同类型的值永远不会深度相等。

    • 数组array的对应元素深度相等时,数组值是深度相等的。

    • 当结构体struct值如果其对应的字段(包括导出和未导出的字段)都是深度相等的,则该值是深度相等的。

    • 当函数func值如果都是零,则是深度相等;否则就不是深度相等。

    • 当接口interface值如果持有深度相等的具体值,则深度相等。

    • 当切片slice序号相同,如果值,指针都相等,那么就是深度相等的

    • 当哈希表map相同的key,如果值,指针都相等,那么就是深度相等的。

    通过以上规则可以看到,reflect.DeepEqual是可以比较struct的,同时也可以用来比较slicemap

    示例代码:

    package mainimport (    "fmt"    "reflect")type People struct {    Name string    Hobby []string}func main() {        p1 := People{Name: "test", Hobby: []string{"唱", "跳"}}        p2 := People{Name: "test", Hobby: []string{"唱", "跳"}}        if reflect.DeepEqual(p1, p2) {            fmt.Println("struct true")        }        mp1 := map[int]int{1: 1, 2: 2}    mp2 := map[int]int{1: 1, 2: 2}        if ok := reflect.DeepEqual(mp1, mp2);ok {fmt.Println("mp1 == mp2!")    } else {fmt.Println("mp1 != mp2!")    }    }

    cmp.Equal()

    go-cmp是 Google 开源的比较库,它提供了丰富的选项。

    对比规则

    • 在经过路径过滤,值过滤和类型过滤之后,会生一些忽略、转换、比较选项,如果选项中存在忽略,则忽略比较,如果转换器和比较器的数据大于1,则会panic(因为比较操作不明确)。如果选项中存在转换器,则调用转换器转换当前值,再递归调用转换器输出类型的Equal。如果包含一个比较器。则比较使用比较器比较当前值。否则进入下一比较阶段。

    • 如果比较值有一个(T) Equal(T) bool 或者 (T) Equal(I) bool,那么,即使x与y是nil,也会调用x.Equal(y)做为结果。如果不存在这样的方法,则进入下一阶段。

    • 在最后阶段,Equal方法尝试比较x与y的基本类型。使用go语言的 == 比较基本类型(bool, intX, float32,float64, complex32,complex64, string, chan)。

    • 在比较struct时,将递归的比较struct的字段。如果结构体包含未导出的字段,函数会panic可以通过指定cmpopts.IgnoreUnexported来忽略未导出的字段,也可以使用cmp.AllowUnexported来指定比较未导出的字段。

    示例代码:

    package mainimport (  "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: "test", Age: 18}  u2 := User{Name: "test", Age: 18}  fmt.Println("u1 == u2?", u1 == u2)  //true  fmt.Println("u1 equals u2?", cmp.Equal(u1, u2)) //true  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) //true  fmt.Println("u1 equals u2 with same pointer?", cmp.Equal(u1, u2)) //true  u2.Contact = c2  fmt.Println("u1 == u2 with different pointer?", u1 == u2) //false   fmt.Println("u1 equals u2 with different pointer?", cmp.Equal(u1, u2)) //true}

    cmp和DeepEqual的区别

    • 安全:cmp.Equal()函数不会比较未导出字段(即字段名首字母小写的字段)。遇到未导出字段,cmp.Equal()直接panic,reflect.DeepEqual()会比较未导出的字段。

    • 强大:cmp.Equal()函数提供丰富的函数参数,让我们可以实现:忽略部分字段,比较零值,转换某些值,允许误差等。

    • 共同点:两种比较类型,都会比较:对象类型,值,指针地址等。切片会按照索引比较值,map是按照key相等比较值。

    性能比较

    简单类型的==对比速度最快

    复杂类型,自己知道结构之后写的自定义对比速度次之

    复杂结构且不确定结构的,使用cmp.Equal()或者reflect.DeepEqual()都可以,就是效率低点

    assert.Equal()底层使用的就是reflect.DeepEqual()

    关于“Golang怎么判断struct/slice/map是否相等”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网GO频道,小编每天都会为大家更新不同的知识点。

    您可能感兴趣的文档:

    --结束END--

    本文标题: Golang怎么判断struct/slice/map是否相等

    本文链接: https://www.lsjlt.com/news/346437.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作