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数据的一些操作,提高了代码的可读性和开发效率,减少了冗余的逻辑,更加简洁。

参考

相关推荐
梦想很大很大16 小时前
使用 Go + Gin + Fx 构建工程化后端服务模板(gin-app 实践)
前端·后端·go
lekami_兰21 小时前
MySQL 长事务:藏在业务里的性能 “隐形杀手”
数据库·mysql·go·长事务
却尘1 天前
一篇小白也能看懂的 Go 字符串拼接 & Builder & cap 全家桶
后端·go
ん贤1 天前
一次批量删除引发的死锁,最终我选择不加锁
数据库·安全·go·死锁
mtngt112 天前
AI DDD重构实践
go
Grassto3 天前
12 go.sum 是如何保证依赖安全的?校验机制源码解析
安全·golang·go·哈希算法·go module
Grassto5 天前
11 Go Module 缓存机制详解
开发语言·缓存·golang·go·go module
程序设计实验室6 天前
2025年的最后一天,分享我使用go语言开发的电子书转换工具网站
go
我的golang之路果然有问题6 天前
使用 Hugo + GitHub Pages + PaperMod 主题 + Obsidian 搭建开发博客
golang·go·github·博客·个人开发·个人博客·hugo
啊汉8 天前
古文观芷App搜索方案深度解析:打造极致性能的古文搜索引擎
go·软件随想