golang切片内存应用技巧详解

作者:kevinyan 时间:2024-05-21 10:19:38 

在 Go 语言中切片是使用非常频繁的一种聚合类型,它代表变长的序列,底层引用一个数组对象。一个切片由三个部分构成:指针、长度和容量。指针指向该切片自己第一个元素对应的底层数组元素的内存地址。

切片的类型声明如下:


type slice struct {
array unsafe.Pointer
len  int
cap  int
}

多个切片之间可以共享底层数组的数据,并且引用的数组区间可能重叠。利用切片 的这个特性我们可以在原有内存空间中对切片进行反转、筛选和去重等操作,这样就不用声明一个指向新内存的切片来存储结果,从而节省了内存空间以及扩展底层数组的消耗,这在切片长度足够大时效果就会非常显著。

下面这些例子都是在切片底层数组的内存空间上进行的操作,需要注意的是这些操作在底层数组上生成新切片的同时也会更改底层数组。

删除指定位置的元素

下面的函数从原切片中删除索引位置i上的元素


func remove(slice []int, i int) []int {
 copy(slice[i:], slice[i+1:])
 return slice[:len(slice)-1]
}

func main() {
 s := []int{5, 6, 7, 8, 9}
 fmt.Println(remove(s, 2)) // "[5 6 8 9]"
}

内置的copy函数可以方便地将一个切片复制另一个相同类型的切片上。

筛选元素

下面的函数从输入的源切片中筛选出满足条件的切片元素,返回一个满足条件的元素组成的新切片。


type funcType func(T) bool //代表筛选逻辑函数,可以按需实现

func filter(a []T, f funcType) []T {
 b := a[:0]
 for _, x := range a {
  if f(x) {
  b = append(b, x)
  }
 }
 return b
}

反转切片


func reverse(a []T) []T {
 for i := len(a)/2-1; i >= 0; i-- {
   opp := len(a)-1-i
  a[i], a[opp] = a[opp], a[i]
}

return a
}

分组切片

下面的函数接收一个[]int 类型的源切片actions, 返回一个按指定长度分组的嵌套切片(解释起来好难,用过PHP 的同学可以理解为 Go 版本的array_chunk 函数,没用过的看下面例子)。假设切面值为:[]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9},设置分组中元素长度batchSize为3,函数调用后返回的分组后的切片为[[0 1 2] [3 4 5] [6 7 8] [9]]


func chunk(actions []int, batchSize int) []int {
var batches [][]int

for batchSize < len(actions) {
  actions, batches = actions[batchSize:], append(batches, actions[0:batchSize:batchSize])
}
batches = append(batches, actions)

return batches
}

func main() {
actions := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
batchSize := 3
 chunks = chunk(actions, batchSize)
 //chunks 为[[0 1 2] [3 4 5] [6 7 8] [9]]
}

这里顺便说一下,完整的切片表达式形式如下:


input[low:high:max]

最后一个 max 的作用是,生成的切片的cap(容量)为max - low。

原地去重(只针对可比较的切片类型)


import "sort"

func main() {
in := []int{3,2,1,4,3,2,1,4,1} // any item can be sorted
sort.Ints(in)
j := 0
for i := 1; i < len(in); i++ {
   if in[j] == in[i] {
     continue
}
j++

in[j] = in[i]
}
result := in[:j+1]
fmt.Println(result) // [1 2 3 4]
}

文章中部分例子来自golang 官方的 GitHub 的 wiki ,在这个 wiki 里介绍了很多的切片使用技巧,了解更多可以访问golang 的 GitHub Wiki https://github.com/golang/go/wiki/SliceTricks#filtering-without-allocating

来源:https://juejin.im/post/5de63b35f265da33df77d206

标签:golang,切片,内存应用
0
投稿

猜你喜欢

  • JavaScript正则表达式的简单应用:高亮显示

    2008-07-20 12:46:00
  • 从零学Python之入门(五)缩进和选择

    2022-03-04 13:11:24
  • Pandas高级教程之Pandas中的GroupBy操作

    2022-04-14 19:22:25
  • MySQL Index Condition Pushdown(ICP)性能优化方法实例

    2024-01-19 20:08:25
  • pytorch中的自定义数据处理详解

    2023-08-21 09:31:35
  • Python使用Numpy模块读取文件并绘制图片

    2022-03-11 07:11:58
  • python使用matplotlib画柱状图、散点图

    2023-05-18 11:50:06
  • Python演化计算基准函数详解

    2021-02-13 19:55:32
  • pytorch训练时的显存占用递增的问题解决

    2021-04-20 07:12:45
  • Python 串口读写的实现方法

    2021-04-24 13:25:12
  • 网页设计中的对比原则与接近性原则

    2010-03-30 14:51:00
  • 基于vue-upload-component封装一个图片上传组件的示例

    2024-05-10 14:14:42
  • Python绘制牛奶冻曲线(高木曲线)案例

    2022-04-05 16:35:08
  • Python 中的range(),以及列表切片方法

    2022-04-22 16:22:53
  • webpack-dev-server自动更新页面方法

    2024-04-19 09:48:10
  • python读取html中指定元素生成excle文件示例

    2021-04-08 19:51:11
  • Python详解复杂CSV文件处理方法

    2021-04-05 11:12:02
  • 利用python Selenium实现自动登陆京东签到领金币功能

    2021-11-09 12:00:33
  • django中瀑布流写法实例代码

    2022-08-04 11:11:26
  • 用Vue编写抽象组件的方法

    2024-05-10 14:10:30
  • asp之家 网络编程 m.aspxhome.com