Go1.22 Slices 的一些变化

简介

在最新的Go 1.22 rc版本中, Slices增加了一些新特性。这些变更涉及Concat、Compact、CompactFunc、Delete、DeleteFunc、Replace、Insert等函数,更方便开发者对切片数据进行处理。本文将简介一下这些变化、优势和使用时需要注意的地方。

1. Concat

go 复制代码
// Concat returns a new slice concatenating the passed in slices.
func Concat[S ~[]E, E any](slices ...S) S

新增的Concat将传入的切片连接起来,返回一个新的切片。在之前版本版本,在拼接切片时我们或是使用迭代或者循环的方式,例如

go 复制代码
package main

import "fmt"

func main() {
    slice1 := []int{1, 2, 3}
    slice2 := []int{4, 5, 6}
    result := Concat(slice1, slice2)
    fmt.Println(result) 
}

func Concat(slices ...[]int) []int {
    var result []int
    for _, slice := range slices {
        result = append(result, slice...)
    }
    return result
}
// 输出 [1 2 3 4 5 6]

rc版本中,新增加了slice.Concat,详细如下:

go 复制代码
import "slices" 
result := slices.Concat(slice1, slice2)
// 输出 [1 2 3 4 5 6]

可见,concat可读性更高且更加简洁。

2 Delete、Compact、Replace 变化

缩小切片大小的函数(DeleteDeleteFuncCompactCompactFuncReplace)现在将新长度和旧长度之间的元素归零。

Delete

go 复制代码
// Delete removes the elements s[i:j] from s, returning the modified slice.
// Delete panics if j > len(s) or s[i:j] is not a valid slice of s.
// Delete is O(len(s)-i), so if many items must be deleted, it is better to
// make a single call deleting them all together than to delete one at a time.
// Delete zeroes the elements s[len(s)-(j-i):len(s)].
func Delete[S ~[]E, E any](s S, i, j int) S
 

Delete 1.22之前的版本:

csharp 复制代码
newSlice11 := slices.Delete(slice1, 2, 3)
fmt.Println(newSlice11)
//输出
[1 2]
[1 2 3]

Delete 1.22rc版本中

csharp 复制代码
newSlice11 := slices.Delete(slice1, 2, 3)
fmt.Println(newSlice11)
//输出 
[1 2]        
[1 2 0] 

Compact

go 复制代码
// Compact将连续运行的相等元素替换为单个副本。
//这类似于Unix上的uniq命令。
// Compact修改片s的内容并返回修改后的片;
//可以有更小的长度。
// Compact将新长度和原长度之间的元素归零。
func Compact[S ~[]E, E comparable](s S) S 

Compact 1.22之前的版本:

go 复制代码
slice3 := []int{1, 1, 2, 3, 4, 6}
seq := slices.Compact(slice3)
fmt.Println(seq)
fmt.Println(slice3) 
//输出
[1 2 3 4 6]
[1 2 3 4 6 6]

Compact 1.22 rc版本中

go 复制代码
//输出
[1 2 3 4 6]  
[1 2 3 4 6 0]

Replace

go 复制代码
// Replace将元素s[i:j]替换为给定的v,并返回
//修改切片。
//如果j > len(s)或s[i:j]不是s的有效切片,则替换panic。
//当len(v) < (j-i)时,将新长度与原长度之间的元素替换为零。
func Replace[S ~[]E, E any](s S, i, j int, v ...E) S 
go 复制代码
slice2 := []int{4, 5, 6}
newSlice2 := slices.Replace(slice2, 0, 2, 99)
fmt.Println(newSlice2) //
fmt.Println(slice2)    //

之前的版本:

csharp 复制代码
[99 6]
[99 6 6]

1.22 rc版本中

csharp 复制代码
[99 6]  
[99 6 0]

3.Insert 可能 panic

Insert现在,如果参数i超出范围,总是会出现panic 。以前,如果没有要插入的元素,它不会在这种情况下出现恐慌。

在下面的例子中,往slice的x位置插入一个元素,但是没有具体的值。

之前的版本

go 复制代码
slice2 := []int{4, 5, 6}
newSlice2 := slices.Insert(slice2, 4)
fmt.Println(newSlice2) 
// 输出 [4 5 6]

1.22 版本

go 复制代码
panic: runtime error: slice bounds out of range [4:3]

可见,之前版本可以正常执行,1.22会抛出异常。

总结

Go 1.22中,Slice有一些新特性的变化,包括:新增函数Concat用于连接多个切片。缩小切片大小的函数(DeleteDeleteFuncCompactCompactFuncReplace)现在将新长度和旧长度之间的元素归零。Insert现在,如果参数i超出范围,总是会出现恐慌。以前,如果没有要插入的元素,它不会在这种情况下出现恐慌。虽然不是大的特性变化,但确实方便了开发者对slice数据的一些操作,提高了代码的可读性和开发效率,减少了冗余的逻辑,更加简洁。

参考

相关推荐
梁梁梁梁较瘦2 天前
边界检查消除(BCE,Bound Check Elimination)
go
梁梁梁梁较瘦2 天前
指针
go
梁梁梁梁较瘦2 天前
内存申请
go
半枫荷2 天前
七、Go语法基础(数组和切片)
go
梁梁梁梁较瘦3 天前
Go工具链
go
半枫荷3 天前
六、Go语法基础(条件控制和循环控制)
go
半枫荷4 天前
五、Go语法基础(输入和输出)
go
小王在努力看博客4 天前
CMS配合闲时同步队列,这……
go
Anthony_49264 天前
逻辑清晰地梳理Golang Context
后端·go
Dobby_056 天前
【Go】C++ 转 Go 第(二)天:变量、常量、函数与init函数
vscode·golang·go