Golang比较两个slice是否相等的问题

 更新时间:2023年03月22日 16:10:07   作者:ccgkk  
本文主要介绍了Golang比较两个slice是否相等的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1、为什么在Golang中无法直接使用==来比较两个slice?

和数组不同的是,slice无法做比较,因此不能使用==来测试两个slice是否拥有相同的元素。这里主要是两个原因:

首先和数组元素不同,slice元素是非直接的,有可能slice可以包含它自身。虽然有办法处理这种特殊情况,但是始终没有一种方法是简单、高效、直观的;
其次,因为slice的元素不是直接的,所以如果底层数组元素改变,同一个slice在不同的时间会有不同的元素;

2、如何实现两个slice的比较呢?

标准库里面提供了高度优化的函数bytes.Equal来比较两个字节类型的slice([]byte)

2.1 深度比较

自己写一个方法,首先比较两个slice的长度,再比较两个slice对应位置元素是否相等。

package main

import (
    "fmt"
)

func main() {
    slice1 := []int{1, 3, 4}
    slice2 := []int{1, 2, 4}
    fmt.Printf("Expect:false\tOutput:%v\n", equal(slice1, slice2)) // Expect:false    Output:false
    slice1 = []int{1, 2, 4}
    slice2 = []int{1, 2, 4}
    fmt.Printf("Expect:true\tOutput:%v\n", equal(slice1, slice2)) // Expect:true     Output:true
}

func equal(slice1, slice2 []int) bool {
    // 比较长度
    if len(slice1) != len(slice2) {
        return false
    }
    // 比较对应位置的元素是否相同
    for i := 0; i < len(slice1); i++ {
        if slice1[i] != slice2[i] {
            return false
        } else {
            continue
        }
    }
    return true
}

2.2 使用reflect.DeepEqual函数

使用反射包中提供的DeepEqual可以更加简洁的实现。另外有些时候我们需要对结构体对象进行比较的时候,我们可以使用该函数

package main

import (
    "fmt"
    "reflect"
)

func main() {
    slice1 := []int{1, 3, 4}
    slice2 := []int{1, 2, 4}
    fmt.Printf("Expect:false\tOutput:%v\n", reflect.DeepEqual(slice1, slice2))

    // fmt.Printf("Expect:false\tOutput:%v\n", equal(slice1, slice2))
    slice1 = []int{1, 2, 4}
    slice2 = []int{1, 2, 4}
    fmt.Printf("Expect:true\tOutput:%v\n", reflect.DeepEqual(slice1, slice2))

    // fmt.Printf("Expect:true\tOutput:%v\n", equal(slice1, slice2))
}

3、扩展:如何在map中让slice充当key?⭐️

由于散列表(Golang中map的底层实现原理)仅对元素做浅拷贝,这就要求散列表里面的键在散列表的整个生命周期内必须保持不变。因此正常情况下,我们无法让一个slice作为一个map的键,但是如果有这样的业务需要我们怎么来实现呢?

本质上,其实是将slice按其字面转化为string
%q 该值对应的单引号括起来的go语法字符字面值,必要时会采用安全的转义表示

package main

import "fmt"

// "reflect"

type MyMap map[string]int

func (mm MyMap) Add(list []string) {
    mm[k(list)]++
}

func (mm MyMap) Count(list []string) int {
    return mm[k(list)]
}

func k(list []string) string {
    return fmt.Sprintf("%q", list)
}

func main() {

    slice1 := []string{"1", "3", "4"}
    slice2 := []string{"1", "3", "4"}
    slice3 := []string{"1", "2", "4"}

    m := make(MyMap)

    m.Add(slice1)
    m.Add(slice2)
    m.Add(slice3)

    fmt.Printf("Expect:1\tOutput:%v\n", m.Count(slice2)) // Expect:1        Output:1
    fmt.Printf("Expect:2\tOutput:%v\n", m.Count(slice1)) // Expect:2        Output:2
    fmt.Printf("%v\n", m) // map[["1" "2" "4"]:1 ["1" "3" "4"]:2]
}

到此这篇关于Golang比较两个slice是否相等的问题的文章就介绍到这了,更多相关Golang比较两个slice相等内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 以Golang为例详解AST抽象语法树的原理与实现

    以Golang为例详解AST抽象语法树的原理与实现

    AST 使用树状结构来表达编程语言的结构,树中的每一个节点都表示源码中的一个结构,本文将以GO语言为例,为大家介绍一下AST抽象语法树的原理与实现,希望对大家有所帮助
    2024-01-01
  • GO实现协程池管理的方法

    GO实现协程池管理的方法

    这篇文章给大家介绍GO实现协程池管理的方法,分别使用channel实现协程池和消费者模式实现协程池,本文通过实例代码给大家介绍的非常详细,需要的朋友参考下吧
    2021-07-07
  • Golang使用Decimal库避免运算中精度损失详细步骤

    Golang使用Decimal库避免运算中精度损失详细步骤

    decimal是为了解决Golang中浮点数计算时精度丢失问题而生的一个库,使用decimal库我们可以避免在go中使用浮点数出现精度丢失的问题,下面这篇文章主要给大家介绍了关于Golang使用Decimal库避免运算中精度损失的相关资料,需要的朋友可以参考下
    2023-06-06
  • Golang基于JWT与Casbin身份验证授权实例详解

    Golang基于JWT与Casbin身份验证授权实例详解

    这篇文章主要为大家介绍了Golang基于JWT与Casbin实现身份验证授权实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-08-08
  • go local history本地历史恢复代码神器

    go local history本地历史恢复代码神器

    这篇文章主要为大家介绍了go local history本地历史恢复代码神器的使用功能详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • golang字符串拼接实现方式和区别对比

    golang字符串拼接实现方式和区别对比

    本文介绍了Go语言中字符串拼接的多种方法及其优缺点,推荐使用strings.Builder进行频繁拼接以优化内存分配和性能,同时,还讨论了通过sync.Pool优化高频创建的对象,以减少垃圾回收压力,感兴趣的朋友一起看看吧
    2025-02-02
  • Golang实现http重定向https

    Golang实现http重定向https

    这篇文章介绍了Golang实现http重定向https的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • 深入探索Golang中的SM4加密解密算法

    深入探索Golang中的SM4加密解密算法

    SM4加密算法在安全性、高效性、简单性、标准化和广泛支持等方面具有优势,适用于各种数据保护和加密应用场景,这篇文章就来和大家探索一下Golang中的SM4加密解密算法吧
    2023-06-06
  • 小学生也能看懂的Golang异常处理recover panic

    小学生也能看懂的Golang异常处理recover panic

    在其他语言里,宕机往往以异常的形式存在,底层抛出异常,上层逻辑通过 try/catch 机制捕获异常,没有被捕获的严重异常会导致宕机,go语言追求简洁,优雅,Go语言不支持传统的 try…catch…finally 这种异常
    2021-09-09
  • GO语言对数组切片去重的实现

    GO语言对数组切片去重的实现

    本文主要介绍了GO语言对数组切片去重的实现,主要介绍了几种方法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04

最新评论