首页 > 其他分享 >Go官方放出泛型slices包

Go官方放出泛型slices包

时间:2024-01-31 21:24:21浏览次数:17  
标签:slices int 元素 切片 泛型 func 类型 Go

阅读本文大概需要 6 分钟。

slices 标准库是 Go 1.21 新增的一个包,它提供了许多对切片(slices)进行常见操作的泛型函数,可以适用于任何元素类型的切片。切片是 Go 语言中一种重要的数据结构,它可以动态地存储和管理一组相同类型的元素。切片的底层实现是一个数组,但是切片可以根据需要自动地增长或缩小,而不需要手动分配或释放内存。切片的声明方式如下:

  1.   var s []int // 声明一个 int 类型的空切片
  2.   s = make([]int, 10) // 使用 make 函数创建一个长度为 10 的切片
  3.   s = []int{1, 2, 3} // 使用字面量初始化一个切片

slices 标准库为切片提供了以下几类操作:

  • 搜索:使用二分法在有序的切片中查找某个元素或满足某个条件的元素。

  • 压缩:将切片中连续相等的元素替换为单个元素,从而减少切片的长度。

  • 比较:比较两个切片是否相等或者按照字典序大小关系。

  • 包含:检查切片中是否存在某个元素或满足某个条件的元素。

  • 克隆:创建一个新的切片,复制原切片中的所有元素。

  • 索引:返回切片中某个元素或满足某个条件的元素的索引位置。

  • 插入:在切片中插入一个或多个元素,返回一个新的切片。

  • 排序:对切片中的元素进行排序,可以使用默认的比较函数或自定义的比较函数。

  • 最大值和最小值:返回切片中的最大值或最小值,可以使用默认的比较函数或自定义的比较函数。

  • 移除:从切片中移除一个或多个元素,返回一个新的切片。

  • 反转:将切片中的元素顺序反转,返回一个新的切片。

  • 替换:将切片中的一个或多个元素替换为另一个或多个元素,返回一个新的切片。

实现原理

slices 标准库使用了 Go 1.18 引入的泛型特性,使得它可以支持任何类型的切片。泛型是一种编程语言特性,它允许编写出可以适用于不同类型参数的函数或类型,而不需要重复编写代码。Go 1.18 的泛型特性主要包括以下几个方面:

  • 类型参数:使用方括号声明一个或多个类型参数。例如 func Print[T any](t ...T) 表示定义了一个泛型函数 Print,它接受任何类型 T 的切片作为参数。

  • 类型约束:使用关键字 constraints 定义一个类型约束,它表示一组允许的类型参数。例如 type Ordered interface { constraints.Ordered } 表示定义了一个类型约束 Ordered,它只允许实现了 constraints.Ordered 接口(即支持 <, <=, >, >= 操作符)的类型参数。类型约束可以用在函数或类型定义中,例如 func Max[T Ordered](t1, t2 T) 表示定义了一个泛型函数 Max,它接受两个 Ordered 类型参数,并返回其中较大者。

  • 泛型类型:使用类型参数定义一个泛型类型,例如 type Stack[T any] struct { data []T } 表示定义了一个泛型类型 Stack,它是一个栈结构,可以存储任何类型 T 的元素。

  • 泛型实例化:使用具体的类型参数实例化一个泛型函数或类型,例如 Print[int](s) 表示调用 Print 函数,并将 int 类型作为类型参数 T。如果类型参数可以从上下文推断出来,可以省略不写,例如 Print(s)

slices 标准库中的泛型函数大多使用了一个类型参数 E,表示切片的元素类型。例如 func BinarySearch[S ~[]E, E cmp.Ordered](x S, target E) (int, bool) 表示定义了一个泛型函数 BinarySearch,它接受一个有序的切片 x 和一个目标元素 target,都是 E 类型,并返回 target 在 x 中的索引位置和是否找到的布尔值。E 类型必须满足 Ordered 类型约束,即支持比较操作符。

slices 标准库中的泛型函数还使用了一些内置的泛型函数,例如 sort.Slice 和 copy,它们也可以适用于任何类型的切片。例如 sort.Slice(x, func(i, j int) bool { return x[i] < x[j] }) 表示对切片 x 进行排序,使用默认的比较函数。copy(dst, src) 表示将切片 src 中的元素复制到切片 dst 中。

应用场景和示例

slices 标准库可以在很多场景中使用,下面我们举一些例子来说明它的用法。

二分搜索

二分搜索是一种在有序的切片中查找某个元素或满足某个条件的元素的算法,它每次将搜索范围缩小一半,直到找到目标元素或搜索范围为空。slices 标准库提供了两个二分搜索的函数:

  • func BinarySearch[S ~[]E, E cmp.Ordered](x S, target E) (int, bool):在有序的切片 x 中查找目标元素 target,并返回其索引位置和是否找到的布尔值。

  • func BinarySearchFunc[S ~[]E, E, T any](x S, target T, cmp func(E, T) int) (int, bool):在有序的切片 x 中查找满足自定义比较函数 cmp 的元素,并返回其索引位置和是否找到的布尔值。cmp 函数接受两个参数 e 和 t,分别是切片 x 的元素和目标值 target,并返回一个整数表示比较结果。如果 e < t,则返回负数;如果 e == t,则返回零;如果 e > t,则返回正数。

下面是一个使用二分搜索的例子:

  1.   package main
  2.    
  3.   import (
  4.    "fmt"
  5.    "slices"
  6.   )
  7.    
  8.   func main() {
  9.    // 创建一个有序的 int 切片
  10.    x := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
  11.    
  12.    // 使用 BinarySearch 在 x 中查找 5
  13.    i, found := slices.BinarySearch(x, 5)
  14.    fmt.Printf("BinarySearch: found = %t, i = %d\n", found, i) // BinarySearch: found = true, i = 4
  15.    
  16.    // 使用 BinarySearch 在 x 中查找 10
  17.    i, found = slices.BinarySearch(x, 10)
  18.    fmt.Printf("BinarySearch: found = %t, i = %d\n", found, i) // BinarySearch: found = false, i = 9
  19.    
  20.    // 使用 BinarySearchFunc 在 x 中查找第一个大于等于 6 的元素
  21.    i, found = slices.BinarySearchFunc(x, 6, func(e int, t int) int {
  22.     if e >= t {
  23.      return 0
  24.     }
  25.     return -1
  26.    })
  27.    fmt.Printf("BinarySearchFunc: found = %t, i = %d\n", found, i) // BinarySearchFunc: found = true, i = 5
  28.   }

Clip, Clone 和 Compact

Clip, Clone 和 Compact 是 slices 标准库中提供的三个用于压缩切片的函数,它们的作用和用法如下:

  • func Clip[S ~[]E, E any](s S) S:返回一个新的切片:s[:len(s):len(s)],从切片中删除未使用的容量。

  • func Clone[S ~[]E, E any](s S) S:返回一个新的切片,它包含了 s 中所有元素的副本。

  • func Compact[S ~[]E, E comparable](s S) S:返回一个新的切片,它将 s 中连续相等的元素替换为单个元素,从而减少切片的长度。E 类型必须满足 comparable 类型约束。

下面是一个使用 Clip, Clone 和 Compact 的例子:

  1.   package main
  2.    
  3.   import (
  4.    "fmt"
  5.    "slices"
  6.   )
  7.    
  8.   func main() {
  9.    x := make([]string, 4, 6)
  10.    x[0] = "a"
  11.    x[1] = "a"
  12.    x[2] = "b"
  13.    x[3] = "c"
  14.    
  15.    // 使用 Clip 返回 x 中前 5 个元素
  16.    y := slices.Clip(x)
  17.    fmt.Println("Clip:", cap(y)) // Clip: 4
  18.    
  19.    // 使用 Clone 返回 x 的副本
  20.    z := slices.Clone(x)
  21.    fmt.Println("Clone:", z) // Clone: [a a b c]
  22.    
  23.    // 使用 Compact 压缩 x 中连续相等的元素
  24.    w := slices.Compact(x)
  25.    fmt.Println("Compact:", w) // Compact: [a b c]
  26.   }

slices 包中还有其他函数就不一一举例了。

slices 包可以满足常见的切片操作,大家可以升级到 Go1.21 版本使用。

标签:slices,int,元素,切片,泛型,func,类型,Go
From: https://www.cnblogs.com/cheyunhua/p/18000148

相关文章

  • golang 正则过滤sql注入的方法
    该方法返回的是一个bool值packagemainimport"regexp"import"fmt"//正则过滤sql注入的方法//参数:要匹配的语句funcFilteredSQLInject(to_match_strstring)bool{//过滤‘//ORACLE注解--/**///关键字过滤update,delete//正则的字符......
  • 谷歌学术指标(Google Scholar Metrics)
    影响因子(ImpactFactor,IF)是上世纪由汤森路透公司开发的,最初主要用途是为科研机构和图书馆选购期刊提供参考,现在被广泛用于衡量期刊的影响力。由于IF是一个相对统计量,所以可公平地评价和处理各类期刊。通常,期刊影响因子越大,它的学术影响力和作用也越大。我们看一下IF的计算方法:IF=......
  • golang中 UTF-8 和GBK格式的转换
    funcmain(){ str:="测试" utf8By:=[]byte(str) gbkBy,_:=Utf8ToGbk(utf8By) //直接打印用string转类型的gkb字节数组,会乱码 fmt.Println("打印GBK",string(gbkBy)) fmt.Println("UTF8字节长度:",len(utf8By),"GBK字节长度:",len(gbkBy)) ......
  • PHP5.6的安装及redis、memcache、mongo扩展
    系统版本:CentOSLinuxrelease7.4.1708(Core)PHP5.6下载地址:wgethttp://am1.php.net/distributions/php-5.6.37.tar.gz需要装好yum的epel-release,这上面有相对应的依赖包,否则依赖包没装好编译会报错!!!安装相关依赖关系包yum-yinstallgccgcc-c++phpphp-mysqbzip2-dev......
  • golang 使用hex包,转换文件的16进制字符、16进制字节数组
    某些特殊情况下需要根据文件的16进制转换成字符在linux系统用vim保存一个文件,写入两行内容这是测试A这是测试B用linux的xxd命令输出文件的16进制字节数组xxd-g1-it.txtunsignedchart_txt[]={0xe8,0xbf,0x99,0xe6,0x98,0xaf,0xe6,0xb5,0x8b,0x......
  • golang gin框架搭建restapi
    初学golang,尝试用gin框架搭建restapi一)源码准备创建go.mod文件,相当于nodejs中的package.jsongomodinitexamples/web-service-gin新建文件main.go,加入以下代码packagemainimport( "net/http" "github.com/gin-gonic/gin")//albumrepresentsdataaboutarecor......
  • Rust 关于 Cargo 和 Crates.io 的内容
    原文链接参考Rust关于Cargo和Crates.io的内容,注意Windows和Linux系统的文件路径差异。目录采用发布配置自定义构建将crate发布到Crates.io编写有用的文档注释常用(文档注释)部分文档注释作为测试注释包含项的结构使用pubuse导出合适的公有API创建Crates.io账号向新c......
  • Go语言的100个错误使用场景(11-20)|项目组织和数据类型
    目录前言2.Codeandprojectorganization2.11没有使用函数式选项模式(#11)2.12项目缺乏组织(#12)2.13创建公共设施包(#13)2.14忽略包名的冲突(#14)2.15代码文档缺失(#15)2.16不使用code-linter(#16)3.Datatypes3.1八进制产生的混乱局面(#17)3.2忽略整型溢出(#18)3.3不理解浮点数(#19)3......
  • 在gin-gonic框架下,gin.context 输出json, 默认会将&转义为\u0026, 怎么将这个转义关
    在gin-gonic中,如果你想要禁止对&等字符进行转义,可以使用gin.Context的PureJSON方法。这个方法允许你自己控制JSON输出,而不会进行字符的转义。以下是一个简单的例子:packagemainimport( "github.com/gin-gonic/gin" "net/http")funcmain(){ router:=gin.Default() ......
  • 修改主板bios开机logo
    1. 下载AFUWIN5.12.zip,ChangeLogov5.2.0.22.zip   2.准备新logo,大小按原大小800*600可以jpg可以bmp3.操作:①原rom:打开AFUWINGUIx64.EXE程序 点击存储保存桌面原rom(建议多复制一个)②换logo图片:打开ChangeLogo64.exe程序 点击loadimage选择原......