Go1.21新增slices包的用法详解

 更新时间:2023年08月17日 08:41:38   作者:路多辛  
Go 1.21新增的 slices 包提供了很多和切片相关的函数,可以用于任何类型的切片,这篇文章主要来和大家介绍一下slices包中相关函数的用法,需要的可以参考一下

slices.BinarySearch

定义如下:

func BinarySearch[S ~[]E, E cmp.Ordered](x S, target E) (int, bool)

在已经排好序的切片(切片必须按递增顺序排序)中搜索目标,如果找到了,返回所在的位置和 true,如果没有找到,则返回目标应该被找到的位置和 false,简单示例如下:

package main
import (
    "fmt"
    "slices"
)
func main() {
    names := []string{"Alice", "Bob", "Vera"}
    n, found := slices.BinarySearch(names, "Vera")
    fmt.Println("Vera:", n, found) // Vera: 2 true
    n, found = slices.BinarySearch(names, "Bill")
    fmt.Println("Bill:", n, found) // Bill: 1 false
}

slices.BinarySearchFunc

定义如下:

func BinarySearchFunc[S ~[]E, E, T any](x S, target T, cmp func(E, T) int) (int, bool)

作用类似 slices.BinarySearch,不同的是使用自定义比较函数。切片必须按递增顺序排序,其中“递增”是由cmp定义的。如果 slice 元素与目标匹配,CMP应该返回 0,如果 slice元素在目标之前,则返回一个负数,如果 slice 元素在目标之后,则返回一个正数。CMP必须实现与片相同的排序,这样,如果CMP (a, t) < 0且CMP (b, t) >= 0,则切中的 a 必须位于 b 之前。

package main
import (
    "cmp"
    "fmt"
    "slices"
)
func main() {
    type Person struct {
        Name string
        Age  int
    }
    people := []Person{
        {"Alice", 55},
        {"Bob", 24},
        {"Gopher", 13},
    }
    n, found := slices.BinarySearchFunc(people, Person{"Bob", 0}, func(a, b Person) int {
        return cmp.Compare(a.Name, b.Name)
    })
    fmt.Println("Bob:", n, found) // Bob: 1 true
}

slices.Clip

定义如下:

func Clip[S ~[]E, E any](s S) S

从切片中删除未使用的容量,返回 s[:len(s):len(s)]。简单示例如下:

package main
import (
    "fmt"
    "slices"
)
func main() {
    names := make([]string, 2, 5)
    names = slices.Clip(names)
    fmt.Printf("长度:%d,容量:%d", len(names), cap(names))
  // 长度:2,容量:2
}

slices.Clone

定义如下:

func Clone[S ~[]E, E any](s S) S

返回切片的副本。因为元素是使用赋值方式复制的,所以这是一个浅克隆。简单实用方法如下:

package main
import (
    "fmt"
    "slices"
)
func main() {
    names := []string{"路多辛的博客", "路多辛的所思所想"}
    namesCopy := slices.Clone(names)
    fmt.Println(namesCopy)
}

slices.Compact

定义如下:

func Compact[S ~[]E, E comparable](s S) S

将连续出现的元素变为一个,类似于 Unix 上的 uniq 命令。Compact 会修改片的内容并返回修改后的片,长度可能会变得更小。简单示例如下:

package main
import (
    "fmt"
    "slices"
)
func main() {
    seq := []int{0, 1, 1, 2, 5, 5, 5, 8}
    seq = slices.Compact(seq)
    fmt.Println(seq) // [0 1 2 5 8]
}

slices.CompactFunc

定义如下:

func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S

类似于 slices.Compact,不同的是使用自定义的函数来比较元素。如果元素的运行结果相等,CompactFunc 将保留第一个元素。简单示例如下:

package main
import (
    "fmt"
    "slices"
    "strings"
)
func main() {
    names := []string{"bob", "Bob", "alice", "Vera", "VERA"}
    names = slices.CompactFunc(names, func(a, b string) bool {
        return strings.ToLower(a) == strings.ToLower(b)
    })
    fmt.Println(names) // [bob alice Vera]
}

slices.Compare

定义如下:

func Compare[S ~[]E, E cmp.Ordered](s1, s2 S) int

使用 cmp.Compare函数来比较 s1 和 s2 的元素。按照顺序比较每一对元素,直到一个元素不等于另一个元素。返回第一个不匹配元素的结果。如果两个切片在其中一个结束之前相等,则认为较短的切片小于较长的切片。如果 s1 == s2,结果为0;如果 s1 < s2,结果为-1;如果 s1 > s2,结果为1。

package main
import (
    "fmt"
    "slices"
)
func main() {
    names := []string{"Alice", "Bob", "Vera"}
    fmt.Println("Equal:", slices.Compare(names, []string{"Alice", "Bob", "Vera"}))
    fmt.Println("V < X:", slices.Compare(names, []string{"Alice", "Bob", "Xena"}))
    fmt.Println("V > C:", slices.Compare(names, []string{"Alice", "Bob", "Cat"}))
    fmt.Println("3 > 2:", slices.Compare(names, []string{"Alice", "Bob"}))
}

运行结果如下:

Equal: 0
V < X: -1
V > C: 1
3 > 2: 1

slices.CompareFunc

定义如下:

func CompareFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, cmp func(E1, E2) int) int

类似于 slices.Compare,不同的是使用自定义的比较函数进行比较。结果是 cmp 的第一个非零结果;如果 cmp 总是返回0,则如果 len(s1) == len(s2) 结果为0,如果len(s1) < len(s2)结果为-1,如果 len(s1) > len(s2) 结果为1。简单示例如下:

package main
import (
    "cmp"
    "fmt"
    "slices"
    "strconv"
)
func main() {
    numbers := []int{0, 43, 8}
    strings := []string{"0", "0", "8"}
    result := slices.CompareFunc(numbers, strings, func(n int, s string) int {
        sn, err := strconv.Atoi(s)
        if err != nil {
            return 1
        }
        return cmp.Compare(n, sn)
    })
    fmt.Println(result) // 1
}

slices.Contains

定义如下:

func Contains[S ~[]E, E comparable](s S, v E) bool

用于判断 s 是否包含 v。简单示例如下:

package main
import (
    "fmt"
    "slices"
)
func main() {
    names := []string{"Alice", "Bob", "Vera"}
    fmt.Println(slices.Contains(names, "Bob")) // true
}

slices.ContainsFunc

定义如下:

func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool

用于判断 s 中是否至少有一个元素 e 满足 f(e)。简单示例如下:

package main
import (
    "fmt"
    "slices"
)
func main() {
    numbers := []int{0, 42, -10, 8}
    hasNegative := slices.ContainsFunc(numbers, func(n int) bool {
        return n < 0
    })
    fmt.Println("Has a negative:", hasNegative)// true
    hasOdd := slices.ContainsFunc(numbers, func(n int) bool {
        return n%2 != 0
    })
    fmt.Println("Has an odd number:", hasOdd) // false
}

【参考资料】

Package slices(https://golang.google.cn/pkg/slices/

以上就是Go1.21新增slices包的用法详解的详细内容,更多关于Go1.21 slices包的资料请关注脚本之家其它相关文章!

相关文章

  • 详解golang RWMutex读写互斥锁源码分析

    详解golang RWMutex读写互斥锁源码分析

    这篇文章主要介绍了详解golang RWMutex读写互斥锁源码分析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • 一文初探Go语言中的reflect反射包

    一文初探Go语言中的reflect反射包

    这篇文章主要和大家分享一下Go语言中的reflect反射包,文中的示例代码讲解详细,对我们学习Go语言有一定的帮助,需要的小伙伴可以参考一下
    2022-12-12
  • Go sync WaitGroup使用深入理解

    Go sync WaitGroup使用深入理解

    这篇文章主要为大家介绍了Go sync WaitGroup使用深入理解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-10-10
  • go语言搬砖之go jmespath实现查询json数据

    go语言搬砖之go jmespath实现查询json数据

    这篇文章主要为大家介绍了go语言搬砖之go jmespath实现查询json数据,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • Golang日志库logrus的介绍与使用示例代码

    Golang日志库logrus的介绍与使用示例代码

    Logrus是Go语言的一个功能丰富的日志库,支持结构化日志和多级别日志记录,它兼容标准log库,并可通过自定义Hooks和Formatter进行高度定制化,支持集成如syslog等系统,便于管理和分析,Logrus还支持自定义日志颜色和格式,以及根据日志级别进行不同处理,如panic和exit
    2024-10-10
  • Golang 中实现 Set的思路详解

    Golang 中实现 Set的思路详解

    本文介绍了Go中两种set的实现原理,并在此基础介绍了对应于它们的两个包简单使用,本文介绍的非常详细,需要的朋友参考下吧
    2024-01-01
  • 将Go项目发布到Go官方仓库的完整流程

    将Go项目发布到Go官方仓库的完整流程

    本文详细介绍了如何将Go项目发布到Go官方仓库(通过GoModuleProxy),包括准备工作、项目结构设计、Go模块初始化、代码质量保障、提交到代码托管平台、发布版本、使用GoModuleProxy、维护和更新等内容,帮助开发者轻松分享自己的技术成果,需要的朋友可以参考下
    2026-05-05
  • Go语言编程入门超级指南

    Go语言编程入门超级指南

    这篇文章主要介绍了Go语言编程的入门指南,包括对Go的变量及函数的基本介绍,需要的朋友可以参考下
    2016-01-01
  • Golang编程实现生成n个从a到b不重复随机数的方法

    Golang编程实现生成n个从a到b不重复随机数的方法

    这篇文章主要介绍了Golang编程实现生成n个从a到b不重复随机数的方法,结合实例形式分析了Go语言字符串操作及随机数生成的相关操作技巧,需要的朋友可以参考下
    2017-01-01
  • Go 中闭包的底层原理

    Go 中闭包的底层原理

    这篇文章主要介绍了Go 中闭包的底层原理,闭包的基本原理是一种现象,一个函数内引用了外部的局部变量的现象,带着些许的了解和小编一起进入文章正题学习
    2021-10-10

最新评论